Search code examples
node.jsdockermacossveltekitsveltekit-adapter-node

SvelteKit `TypeError: fetch failed` `Error: connect ECONNREFUSED 127.0.0.1:8002`


In a SvelteKit server action (+page.server.js), I am attempting to use SvelteKit's fetch implementation to call an API endpoint.

This is hosted within a Docker container on port 8000, trying to call a GraphQL service served from another container on port 8002.

import { fail } from '@sveltejs/kit'

export const actions = {
    default: async ({ request, cookies, fetch }) => {
        const form = await request.formData()
        const username = form.get('username')
        const password = form.get('password')
        if (!username || !password) return fail(400, { username })

        const result = await fetch('http://localhost:8002/sessions', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            // Omitted because it doesn't appear to be the cause of this issue.
            body: JSON.stringify({}),
        })

        console.log({result})
    }
}

The call to fetch throws this error:

TypeError: fetch failed
    at node:internal/deps/undici/undici:13484:13
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5) {
  [cause]: Error: connect ECONNREFUSED 127.0.0.1:8002
      at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1615:16)
      at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
    errno: -111,
    code: 'ECONNREFUSED',
    syscall: 'connect',
    address: '127.0.0.1',
    port: 8002
  }
}

I've seen advice elsewhere to reference 127.0.0.1 instead of localhost, but that still doesn't resolve the issue for me.

Using Postman to call the same endpoint with the same info works fine, so this all seems to be an issue with SvelteKit/Node connecting to the API service.


Solution

  • Because I'm using Docker on macOS, I need to reference other local containers with host.docker.internal instead of localhost or 127.0.0.1:

    const result = await fetch('http://host.docker.internal:8002/sessions', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({}),
    })
    

    I read that this also applies if you're running Docker on Windows.