can't fetch external urls from node (timeout error)

I can’t figure out how to fetch external urls from my node app.
I’m really stuck, thank you for any help.

I have boiled it down to this very simple example (which works locally from my machine):

const run = async () => {
	console.log(1)

	const res1 = await (await fetch('https://fly.io')).text()
	console.log({ res1 })

	console.log(2)
}

run()

Error

1
(node:613) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
node:internal/deps/undici/undici:11118
    Error.captureStackTrace(err, this);
          ^

TypeError: fetch failed
    at Object.fetch (node:internal/deps/undici/undici:11118:11)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async run (file:///app/flydebug.js:3:22) {
  cause: ConnectTimeoutError: Connect Timeout Error
      at onConnectTimeout (node:internal/deps/undici/undici:6625:28)
      at node:internal/deps/undici/undici:6583:50
      at Immediate._onImmediate (node:internal/deps/undici/undici:6614:13)
      at process.processImmediate (node:internal/timers:471:21) {
    code: 'UND_ERR_CONNECT_TIMEOUT'
  }
}

This, however, works

From fly ssh console

curl https://fly.io

Some bits from fly ssh console > printenv

FLY_REGION=fra
NODE_VERSION=18.12.1
SSH_DNS_SERVER=[fdaa::3]:53

fly.toml

app = "di"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[mounts]
  source = "data"
  destination = "/app/data"

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[[services]]
  http_checks = []
  internal_port = 3000
  processes = ["app"]
  protocol = "tcp"
  script_checks = []
  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    force_https = true
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443

  [[services.tcp_checks]]
    grace_period = "1s"
    interval = "15s"
    restart_limit = 0
    timeout = "2s"

Dockerfile

FROM node:18-alpine

WORKDIR /app

COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

COPY . .
RUN yarn vite build

RUN apk add --no-cache curl

CMD [ "yarn", "start" ]
1 Like

Hi,

Yep, I’ve had that before when running Node on Alpine. Check out this thread:

Essentially the “fix” is not using Alpine as the base image. That resolved the issue for both me and this other guy anyway :slight_smile:.

1 Like

I saw your thread before, but forgot to mention it.
I tried your suggestion and various other distributions without success.
But thank you for your help anyway, I appreciate it!! :slight_smile:

I just found a solution to my problem though:

I destroyed the app on fly.io and re-deployed it as-is on a new instance, problem gone.

Everything else stayed the same, apart from adding these to my Dockerfile (new lines prefixed with a +):

FROM node:18-alpine

+ LABEL fly_launch_runtime="nodejs"

WORKDIR /app

COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile

COPY . .
RUN yarn prisma migrate deploy
RUN yarn prisma generate
RUN yarn vite build

+ ENV NODE_ENV production

CMD [ "yarn", "start" ]

The only other difference I can think of, is that the previous instance was initially using a buildpack, then was changed to use a Dockerfile. Maybe that affected the instance in some permanent way.

In any case, what I did was basically to “to turn it off and on again”. It worked, I just wish I had thought of that earlier.

1 Like