Variables no longer available during build process
chachew
HOBBYOP

9 months ago

Months ago i didnt have issues with the variables in my service being used during the build step in railway, now i do!

Im deploying a simple nuxt app and im using zod to verify the env variables. This works perfectly fine in my development environment with my .env file. I added the same variables to my railway service under its variables section. They are there and visible, but the nuxt build process cant seem to see them so my build fails 100% of the time.

My app just runs through the railway auto detected build process..

import { config } from 'dotenv';
import { expand } from 'dotenv-expand';

import { ZodError, z } from 'zod';

const stringBoolean = z.coerce
  .string()
  .transform((val) => {
    return val === 'true';
  })
  .default('false');

const EnvSchema = z.object({
  NODE_ENV: z.string().default('development'),
  DATABASE_URL: z.string(),
  DATABASE_SERVICE_ROLE: z.string(),
  DATABASE_ANON_KEY: z.string(),
  DB_MIGRATING: stringBoolean,
  DB_SEEDING: stringBoolean
});

export type EnvSchema = z.infer<typeof EnvSchema>;

expand(config());
console.log('------', process.env); // <------------- I cant even see them here...

try {
  EnvSchema.parse(process.env);
} catch (error) {
  if (error instanceof ZodError) {
    let message = 'Missing required values in .env:\n';
    error.issues.forEach((issue) => {
      message += issue.path[0] + '\n';
    });
    const e = new Error(message);
    e.stack = '';
    throw e;
  } else {
    console.error(error);
  }
}

export default EnvSchema.parse(process.env);
Solved$10 Bounty

Pinned Solution

teereckzi
FREE

9 months ago

If you call dotenv.config() in your nuxt.config.ts, it might override Railway’s env injection, because Railway already injects them via its container runtime.

5 Replies

teereckzi
FREE

9 months ago

Railway does not expose service environment variables to the build process by default. It used to feel like it did (or maybe your Nuxt app previously deferred validation until runtime), but this behavior is no longer guaranteed.. especially if your app does strict checks during build.

Move .env validation to runtime

This is often the cleanest way. Don’t run Zod.parse() during the build if you can help it.

Instead:

// environment.ts

import { config } from 'dotenv';

import { expand } from 'dotenv-expand';

import { z, ZodError } from 'zod';

const stringBoolean = z.coerce.string().transform((val) => val === 'true').default('false');

const EnvSchema = z.object({

NODE_ENV: z.string().default('development'),

DATABASE_URL: z.string(),

DATABASE_SERVICE_ROLE: z.string(),

DATABASE_ANON_KEY: z.string(),

DB_MIGRATING: stringBoolean,

DB_SEEDING: stringBoolean,

});

export type EnvSchema = z.infer<typeof EnvSchema>;

expand(config());

let parsed: EnvSchema;

try {

parsed = EnvSchema.parse(process.env);

} catch (err) {

if (err instanceof ZodError && process.env.NODE_ENV !== 'production') {

console.warn('Skipping env validation in build step.');

parsed = {} as EnvSchema; // or set defaults

} else {

throw err;

}

}

export default parsed;

Then in your nuxt.config.ts, only call this file at runtime, not at config evaluation time.


teereckzi

Railway does not expose service environment variables to the build process by default. It used to feel like it did (or maybe your Nuxt app previously deferred validation until runtime), but this behavior is no longer guaranteed.. especially if your app does strict checks during build.Move .env validation to runtimeThis is often the cleanest way. Don’t run Zod.parse() during the build if you can help it.Instead:// environment.tsimport { config } from 'dotenv';import { expand } from 'dotenv-expand';import { z, ZodError } from 'zod';const stringBoolean = z.coerce.string().transform((val) => val === 'true').default('false');const EnvSchema = z.object({NODE_ENV: z.string().default('development'),DATABASE_URL: z.string(),DATABASE_SERVICE_ROLE: z.string(),DATABASE_ANON_KEY: z.string(),DB_MIGRATING: stringBoolean,DB_SEEDING: stringBoolean,});export type EnvSchema = z.infer<typeof EnvSchema>;expand(config());let parsed: EnvSchema;try {parsed = EnvSchema.parse(process.env);} catch (err) {if (err instanceof ZodError && process.env.NODE_ENV !== 'production') {console.warn('Skipping env validation in build step.');parsed = {} as EnvSchema; // or set defaults} else {throw err;}}export default parsed;Then in your nuxt.config.ts, only call this file at runtime, not at config evaluation time.

brody
EMPLOYEE

9 months ago

Railway does not expose service environment variables to the build process by default.

Yes, we do.


brody

Railway does not expose service environment variables to the build process by default.Yes, we do.

teereckzi
FREE

9 months ago

Yes.. Railway does expose environment variables to the build process, as long as they are set properly in the Variables panel. So from Railway’s POV, if my service has those env vars in the dashboard, they should be available at build time.


brody

Railway does not expose service environment variables to the build process by default.Yes, we do.

teereckzi
FREE

9 months ago

If you call dotenv.config() in your nuxt.config.ts, it might override Railway’s env injection, because Railway already injects them via its container runtime.


chachew
HOBBYOP

9 months ago

Ok, removing the config portion from my nuxt.config file solved the issue! Thanks!


Status changed to Open chandrika 9 months ago


Status changed to Solved chandrika 9 months ago


Loading...