{"record":{"id":"d2e9933e0db14278","repo":"toeverything/AFFiNE","slug":"invalid-value-value-for-environment-variable","errorCode":null,"errorMessage":"Invalid value \"${value}\" for environment variable ${env}, expected one of ${JSON.stringify(availableValues)}","messagePattern":"Invalid value \"(.+?)\" for environment variable (.+?), expected one of (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/backend/server/src/env.ts","lineNumber":73,"sourceCode":"  NAMESPACE: Namespace;\n  DEPLOYMENT_TYPE: DeploymentType;\n  version: string;\n};\n\nglobalThis.CLS_REQUEST_HOST = 'CLS_REQUEST_HOST';\nglobalThis.CUSTOM_CONFIG_PATH = join(homedir(), '.affine/config');\nglobalThis.readEnv = function readEnv<T>(\n  env: string,\n  defaultValue: T,\n  availableValues?: T[]\n) {\n  const value = process.env[env];\n  if (value === undefined) {\n    return defaultValue;\n  }\n\n  if (availableValues && !availableValues.includes(value as any)) {\n    throw new Error(\n      `Invalid value \"${value}\" for environment variable ${env}, expected one of ${JSON.stringify(\n        availableValues\n      )}`\n    );\n  }\n\n  return value as T;\n};\n\nexport class Env implements AppEnv {\n  NODE_ENV = (process.env.NODE_ENV ?? NodeEnv.Production) as NodeEnv;\n  NAMESPACE = readEnv(\n    'AFFINE_ENV',\n    Namespace.Production,\n    Object.values(Namespace)\n  );\n  DEPLOYMENT_TYPE = readEnv(\n    'DEPLOYMENT_TYPE',","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/env.ts#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"# before\nAFFINE_ENV=prod\nDEPLOYMENT_TYPE=self-hosted\n# after\nAFFINE_ENV=production\nDEPLOYMENT_TYPE=selfhosted","handlingStrategy":"validation","validationCode":"function assertEnv<T>(env: string, value: string | undefined, allowed: readonly T[]): void {\n  if (value !== undefined && !allowed.includes(value as any)) {\n    throw new Error(`Bad ${env}=${value}. Allowed: ${JSON.stringify(allowed)}`);\n  }\n}\nassertEnv('AFFINE_ENV', process.env.AFFINE_ENV, Object.values(Namespace));","typeGuard":"const isNamespace = (v: string): v is Namespace =>\n  (Object.values(Namespace) as string[]).includes(v);","tryCatchPattern":null,"preventionTips":["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."],"tags":["env","config","bootstrap","validation"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}