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

  1. Read the error message: it JSON.stringifies the exact allowed values — copy one verbatim (case-sensitive) into your env.
  2. Check the enum source: AFFINE_ENV -> Namespace (env.ts), DEPLOYMENT_TYPE -> DeploymentType, SERVER_FLAVOR -> Flavor.
  3. Unset the variable to fall back to the documented default if you do not need to override it.
  4. 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

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


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/d2e9933e0db14278. Report an issue: GitHub.