process.env.MY_VAR is undefined while it exists on the host

I’m building a Node.js application (no frameworks, simple stuff on my own). I’m trying to read process.env in my application to get the HTTP port I want my app to listen to.

It works locally using dotenv and a .env file and when I’ve uploaded my secrets to fly.io, here’s what happens:

  • echo $MY_VAR shows the variable value correctly when I ssh into the container (using fly console)
  • console.log(process.env.MY_VAR) gives undefined in the application runtime
  • I’ve checked the build artifact and it contains references to process.env (and there’s no string replacement)
  • my app is a CJS app (no import.meta.env)

Here’s my fly.toml file:

app = 'my-app'
primary_region = 'cdg'

[build]
dockerfile = 'Dockerfile.Backend'

[http_service]
internal_port = 4000
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 1
processes = ['app']

[[vm]]
cpu_kind = 'shared'
cpus = 2
memory_mb = 2048

and the associated Dockerfile.Backend:

FROM node:18-bullseye-slim AS build
WORKDIR /app
RUN npm i -g pnpm
COPY ./package.json ./package.json
COPY ./pnpm-lock.yaml ./pnpm-lock.yaml
COPY ./pnpm-workspace.yaml ./pnpm-workspace.yaml
COPY ./turbo.json ./turbo.json
COPY ./packages/backend ./packages/backend
RUN pnpm install --ignore-scripts --filter backend...
RUN pnpm run build --filter backend


FROM node:18-bullseye-slim AS proddeps
WORKDIR /app
RUN npm i -g pnpm
COPY --from=build ./app/package.json ./package.json
COPY --from=build ./app/pnpm-lock.yaml ./pnpm-lock.yaml
COPY --from=build ./app/pnpm-workspace.yaml ./pnpm-workspace.yaml
COPY --from=build ./app/turbo.json ./turbo.json
COPY --from=build ./app/packages/backend/dist ./packages/backend/dist
COPY --from=build ./app/packages/backend/src/infrastructure/database/prisma ./packages/backend/src/infrastructure/database/prisma
COPY --from=build ./app/packages/backend/package.json ./packages/backend/package.json
RUN pnpm install --prod
RUN pnpm db:generate:schema

FROM node:18-bullseye-slim AS runner
WORKDIR /app
RUN npm i -g pnpm
COPY --from=proddeps /app .
EXPOSE 4000
CMD [ "pnpm", "run", "start:backend" ]

Does anybody know what’s going on here? First time I’m encountering this issue with fly :sweat_smile:

That does seem weird. The only thing I can think of in this situation is dotenv fudging the variable. Try removing it.

Also it might be worth doing a quick test by adding a hard-coded env in fly.toml:

[env]
  ABC = "example"

Not for a secret key etc. Just to see if process.env.ABC is available at run-time.

I tested both the solutions and I still have the issue.

=> removing dotenv has not changed the result
=> logging process.env.ABC gave undefined

Can you try updating to node 20.x or even 22.x? I haven’t had any env issues on my end.
Also: it’s hard to debug w/o any source code.

I am having the same issue since like 3 hours ago. Exported vars to my app on fly.io. Checked for any misspelling, console.logged the vars; console.log(process.env.[thevar]) shows undefined.

[edit]
1.159 process.env.ABC undefined
This is what I get when running console.log('process.env.ABC', process.env.ABC);
The issue stays the same after changing to newest node version

# Start with a Node.js base image
FROM node:22.6.0

Moreover, env vars where loaded via

fly secrets import -a [theapp] < .env.[theenv]

I had no such issues a few days ago.

huh can either of you put up a min repro? I just redeployed my app and the envs are working.

Hi @greg , I tried to add the dummy env var via the fly.toml file. I still get the same issue (process.env.MY_VAR is undefined while it exists on the host - #6 by patrick-assoa-adou)

@patrick-assoa-adou Er … strange. Those variables should be there at run-time. Either via the fly.toml or the secret.

Not sure what has changed. It might need someone from Fly to debug.

@greg I see. I sent an email to support. Waiting to see their answer and suggestions.

1 Like

I’ve created this small repro => GitHub - mfrachet/flyio-repro-dotenv

where I’m checking the env variables in flyio-repro-dotenv/packages/backend/src/infrastructure/configuration/dotenv.ts at main · mfrachet/flyio-repro-dotenv · GitHub

  • If I start the project with a dotenv file and HTTP_PORT set, it works
  • If I do HTTP_PORT=5000 pnpm start:backend it also works

If I set a secret on fly.io for HTTP_PORT and try to build the project, zod is screaming that HTTP_PORT is not defined (same behaviour as described in this issue)

1 Like

I’ve found the issue and as very often, it’s user lands… I’ve been using turborepo v2 and they want the env variables to be explicitly listed in the turbo.json file, which I was not doing (and not doing in other projects using v1).

Sorry for the inconveniance and thanks for your help.

1 Like

Hi folks,
Even in cases where turborepo is not involved, If you fly ssh console to a machine in your app, use the env command, and the secret shows there, then the problem is not with Fly.io building or secret management, but something in your framework or app code. Once the machine is running, secrets are simply environment variables and there’s no additional magic to how they are presented to the app. If other env variables are visible in process.env, then secrets should, as well.

I just tested deploying a very simple Node app that just spits out the full environment and it worked for me:

var express = require('express');
var app = express();
app.get('/', function (req, res) {
  var foo = JSON.stringify(process.env, null, 2);
  res.send(`Hello World! I am ${foo}`);
});
app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

I tried with Node 16.11.1 and 22.6.0, this works well with both. So this definitely points to a more involved setup (framework, libraries, extra tooling) mangling the environment at runtime, rather than the environment itself being at fault.

  • Daniel
2 Likes

I don’t think that’s the issue. I just tested adding an env via fly.toml:

[env]
HELLO="world"

I then DID NOT add this new env to the turbo.json. I was still able to read the process.env.HELLO in my node app. Turbo is a build pipeline, so it shouldn’t have anything to do w/ runtime environmental variables.

I added the env var keys there and it then worked :blush:

But that’s more to lint/code smell your app for missing/updated env variable names… it shouldn’t affect runtime access of process.env.

As for why it wasn’t working for you before, I’m not sure - possibly because you might be overcomplicated your config env: flyio-repro-dotenv/packages/backend/src/infrastructure/configuration/dotenv.ts at main · mfrachet/flyio-repro-dotenv · GitHub

Do you really need to zod your process.env, when everything is a string?

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.