{"record":{"id":"f98de31d57b9cadd","repo":"hcengineering/platform","slug":"missing-env-variables-missingenv-join-f98de3","errorCode":null,"errorMessage":"Missing env variables: ${missingEnv.join(', ')}","messagePattern":"Missing env variables: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/collaborator/src/config.ts","lineNumber":58,"sourceCode":"}\n\nconst required: Array<keyof Config> = ['Secret', 'ServiceID', 'Port', 'AccountsUrl']\n\nconst config: Config = (() => {\n  const params: Partial<Config> = {\n    Secret: process.env[envMap.Secret],\n    ServiceID: process.env[envMap.ServiceID] ?? 'collaborator-service',\n    Interval: parseInt(process.env[envMap.Interval] ?? '30000'),\n    Port: parseInt(process.env[envMap.Port] ?? '3078'),\n    AccountsUrl: process.env[envMap.AccountsUrl],\n    StorageRetryCount: parseInt(process.env[envMap.StorageRetryCount] ?? '5'),\n    StorageRetryInterval: parseInt(process.env[envMap.StorageRetryInterval] ?? '50')\n  }\n\n  const missingEnv = required.filter((key) => params[key] === undefined).map((key) => envMap[key])\n\n  if (missingEnv.length > 0) {\n    throw Error(`Missing env variables: ${missingEnv.join(', ')}`)\n  }\n\n  return params as Config\n})()\n\nexport default config\n","sourceCodeStart":40,"sourceCodeEnd":65,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/collaborator/src/config.ts#L40-L65","documentation":"The collaborator service config module builds its Config object at import time (IIFE) and throws if any of the required entries — Secret, ServiceID, Port, AccountsUrl — resolve to undefined. Because config is created on module load, the error appears immediately when the process starts, not on first use.","triggerScenarios":"Importing server/collaborator/src/config.ts without env vars SECRET, SERVICE_ID, PORT, or ACCOUNTS_URL set. Port and ServiceID have defaults ('3078' and 'collaborator-service') but are still in `required`, so they trigger too if explicitly set to undefined only; practically SECRET and ACCOUNTS_URL are the usual culprits. The message names the env var(s), e.g. 'SECRET'.","commonSituations":"Running collaborator locally without a .env; k8s secret not mounted so SECRET is absent; forgetting ACCOUNTS_URL when pointing at a different accounts service.","solutions":["Set the env vars listed in the message: typically SECRET and ACCOUNTS_URL (SERVICE_ID/COLLABORATOR_PORT have defaults).","Ensure the k8s Secret providing SECRET is mounted and the env key matches exactly.","Add a .env file or docker --env-file when running locally.","If a var should be optional, add a `?? default` fallback and remove it from the `required` array."],"exampleFix":"// before\nnode bundle.js  # SECRET unset\n// after\nexport SECRET=$(cat /etc/secrets/secret)\nexport ACCOUNTS_URL=https://accounts.example.com\nnode bundle.js","handlingStrategy":"validation","validationCode":"const required = ['SECRET','SERVICE_ID','PORT','ACCOUNTS_URL']\nconst missing = required.filter((k) => process.env[k] === undefined)\nif (missing.length > 0) throw new Error(`Missing env variables: ${missing.join(', ')}`)","typeGuard":"function hasEnv(key: string): boolean {\n  return process.env[key] !== undefined\n}","tryCatchPattern":"// config is created at import time; wrap the import\nlet config\ntry {\n  config = (await import('./config.js')).default\n} catch (err) {\n  if ((err as Error).message.startsWith('Missing env variables:')) {\n    console.error('collaborator config error:', err.message)\n    process.exit(1)\n  }\n  throw err\n}","preventionTips":["Document SECRET and ACCOUNTS_URL as mandatory for collaborator deployments.","Inject the shared secret via a k8s Secret and verify with a startup preflight.","Use --env-file in local scripts so local runs match production.","Add a smoke test that imports config and asserts it does not throw."],"tags":["configuration","environment-variables","startup"],"backgroundTag":"missing-env-var","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}