toeverything/AFFiNE · critical · Error
Invalid value "${value}" for environment variable ${env}, ex
Error message
Invalid value "${value}" for environment variable ${env}, expected one of ${JSON.stringify(availableValues)} What it means
Thrown by the global readEnv() helper (packages/backend/server/src/env.ts:73) at application bootstrap. readEnv reads process.env[env]; if the value is set but not in the optional availableValues allow-list, it throws a plain Error. Because Env is constructed at module load (env.ts:83+), this error crashes the server before it finishes booting. The message enumerates exactly which values are permitted.
Source
Thrown at packages/backend/server/src/env.ts:73
NAMESPACE: Namespace;
DEPLOYMENT_TYPE: DeploymentType;
version: string;
};
globalThis.CLS_REQUEST_HOST = 'CLS_REQUEST_HOST';
globalThis.CUSTOM_CONFIG_PATH = join(homedir(), '.affine/config');
globalThis.readEnv = function readEnv<T>(
env: string,
defaultValue: T,
availableValues?: T[]
) {
const value = process.env[env];
if (value === undefined) {
return defaultValue;
}
if (availableValues && !availableValues.includes(value as any)) {
throw new Error(
`Invalid value "${value}" for environment variable ${env}, expected one of ${JSON.stringify(
availableValues
)}`
);
}
return value as T;
};
export class Env implements AppEnv {
NODE_ENV = (process.env.NODE_ENV ?? NodeEnv.Production) as NodeEnv;
NAMESPACE = readEnv(
'AFFINE_ENV',
Namespace.Production,
Object.values(Namespace)
);
DEPLOYMENT_TYPE = readEnv(
'DEPLOYMENT_TYPE',View on GitHub (pinned to 26c515e050)
Solutions
- Read the error message: it JSON.stringifies the exact allowed values — copy one verbatim (case-sensitive) into your env.
- Check the enum source: AFFINE_ENV -> Namespace (env.ts), DEPLOYMENT_TYPE -> DeploymentType, SERVER_FLAVOR -> Flavor.
- Unset the variable to fall back to the documented default if you do not need to override it.
- After fixing, restart the server — this is a bootstrap-time failure, no retry needed.
Example fix
# before AFFINE_ENV=prod DEPLOYMENT_TYPE=self-hosted # after AFFINE_ENV=production DEPLOYMENT_TYPE=selfhosted
Defensive patterns
Strategy: validation
Validate before calling
function assertEnv<T>(env: string, value: string | undefined, allowed: readonly T[]): void {
if (value !== undefined && !allowed.includes(value as any)) {
throw new Error(`Bad ${env}=${value}. Allowed: ${JSON.stringify(allowed)}`);
}
}
assertEnv('AFFINE_ENV', process.env.AFFINE_ENV, Object.values(Namespace)); Type guard
const isNamespace = (v: string): v is Namespace => (Object.values(Namespace) as string[]).includes(v);
Prevention
- Document every enum-constrained env var with its exact allowed values.
- Add a CI lint that scans .env files against the readEnv allow-lists in env.ts.
- Keep env values lowercase and case-consistent with the enum source.
When it happens
Trigger: Setting an environment variable that is validated against a closed enum to a value outside the enum. Concrete bindings: AFFINE_ENV (must be a Namespace), DEPLOYMENT_TYPE (Affine|Selfhosted), SERVER_FLAVOR (Flavor enum), and any other readEnv call that passes Object.values(SomeEnum) as the third argument.
Common situations: TYPO in .env: AFFINE_ENV=prod instead of production; DEPLOYMENT_TYPE=self-hosted instead of selfhosted; SERVER_FLAVOR=api-server instead of a valid Flavor; copy-pasting a value from an older AFFiNE version whose enum changed; case sensitivity (Production vs production).
Related errors
- Invalid config for module [${module}] with key [${key}] Valu
- invalid_app_config_input
- A config file path is required
- invalid_app_config_input
- App config paths must not overlap: ${overlappingKey} and ${k
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/d2e9933e0db14278.
Report an issue: GitHub.