withastro/astro · error · AstroError
EnvInvalidVariables
EnvInvalidVariables
Error message
The following environment variables defined in `env.schema` are invalid:
${errors} What it means
During the build (non-sync mode), Astro validates every variable declared in `env.schema` against the loaded environment. Any variable whose validator returns `result.ok === false` is collected into an `invalid` list, and if that list is non-empty at the end, Astro aborts the build with `EnvInvalidVariables` listing each failing key, its declared type, and the validator errors.
Source
Thrown at packages/astro/src/env/vite-plugin-env.ts:160
for (const [key, options] of Object.entries(schema)) {
const variable = loadedEnv[key] === '' ? undefined : loadedEnv[key];
if (options.access === 'secret' && !validateSecrets) {
continue;
}
const result = validateEnvVariable(variable, options);
const type = getEnvFieldType(options);
if (!result.ok) {
invalid.push({ key, type, errors: result.errors });
// We don't do anything with validated secrets so we don't store them
} else if (options.access === 'public') {
valid.push({ key, value: result.value, type, context: options.context });
}
}
if (invalid.length > 0 && !sync) {
throw new AstroError({
...AstroErrorData.EnvInvalidVariables,
message: AstroErrorData.EnvInvalidVariables.message(invalidVariablesToError(invalid)),
});
}
return valid;
}
let cachedServerTemplate: string | undefined;
function getTemplates({
schema,
validatedVariables,
loadedEnv,
}: {
schema: EnvSchema;
validatedVariables: Array<ValidVariable>;
loadedEnv: Record<string, string> | null;View on GitHub (pinned to d081033d5f)
Solutions
- Read the error's per-key list and set each missing/invalid variable to a value that satisfies its declared type in the target environment.
- If a value is genuinely optional, give the schema entry a default or make validation tolerant per the env.schema API.
- Confirm `.env` is discoverable: check `envDir` and that Vite's `loadEnv` is picking up the file for the current mode.
- Re-run `astro build`/`astro dev` after fixing to confirm the validator passes.
Example fix
// before
export default defineConfig({
env: { schema: { PORT: env.number() } } // build fails if PORT unset
})
// after — supply a default so validation passes when unset
export default defineConfig({
env: { schema: { PORT: env.number({ default: 4321 }) } } }) Defensive patterns
Strategy: validation
Validate before calling
import { loadEnv } from 'vite';
// Pre-flight: check every schema var resolves and validates before build.
function preflightEnv(schema, mode, envDir) {
const env = loadEnv(mode, envDir, '');
const missing = [];
for (const [key, opt] of Object.entries(schema)) {
if (env[key] === undefined && opt.access !== 'public') missing.push(key);
}
return missing;
} Type guard
null
Try / catch
null
Prevention
- Provide defaults for optional env vars in env.schema.
- Document required env vars in the project README and CI setup.
- Run `astro build` locally with the same mode/env as production before deploy.
When it happens
Trigger: An env variable declared in `env.schema` is missing, malformed, or fails its declared type validator at build time — e.g. `env.number('PORT')` when PORT is unset or non-numeric, or `env.enum(...)` when the value isn't one of the allowed choices. Suppressed only when `sync: true` is set.
Common situations: Forgetting to set a required env var in CI or a deploy target; a `.env` file not loaded because `loadEnv`/`envDir` is misconfigured; a type mismatch after changing a variable's schema type; a secret that's empty or whitespace in production.
Related errors
- CannotExtractFontType
- MissingMiddlewareForInternationalization
- UnsupportedExternalRedirect
- SessionStorageInitError
- EnvPrefixConflictsWithSecret
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/e74e9a24e0baa4e0.
Report an issue: GitHub.