{"record":{"id":"5b0c0fa32c847f04","repo":"actualbudget/actual","slug":"invalid-token-expiration-value-val-value-was","errorCode":null,"errorMessage":"Invalid token_expiration value: ${val}: value was \"${val}\"","messagePattern":"Invalid token_expiration value: (.+?): value was \"(.+?)\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/sync-server/src/load-config.js","lineNumber":43,"sourceCode":"  path.dirname(require.resolve('@actual-app/web/package.json')),\n  'build',\n);\ndebug(`Actual web build path: '${actualAppWebBuildPath}'`);\n\n// Custom formats\nconvict.addFormat({\n  name: 'tokenExpiration',\n  validate(val) {\n    if (val === 'never' || val === 'openid-provider') return;\n    if (typeof val === 'number' && Number.isFinite(val) && val >= 0) return;\n\n    // Handle string values that can be converted to numbers (from env vars)\n    if (typeof val === 'string') {\n      const numVal = Number(val);\n      if (Number.isFinite(numVal) && numVal >= 0) return;\n    }\n\n    throw new Error(\n      `Invalid token_expiration value: ${val}: value was \"${val}\"`,\n    );\n  },\n  coerce(val) {\n    if (val === 'never' || val === 'openid-provider') return val;\n    if (typeof val === 'number') return val;\n\n    // Convert string values to numbers for environment variables\n    if (typeof val === 'string') {\n      const numVal = Number(val);\n      if (Number.isFinite(numVal) && numVal >= 0) return numVal;\n    }\n\n    return val; // Let validate() handle invalid values\n  },\n});\n\n// Main config schema","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/sync-server/src/load-config.js#L25-L61","documentation":"Thrown by the token_expiration validator in load-config.js during server startup. The value must be 'never', 'openid-provider', a finite non-negative number, or a string coercible to such a number; anything else (e.g. '30d', 'abc', negative numbers) aborts config loading with this message.","triggerScenarios":"Setting TOKEN_EXPIRATION env var to a non-numeric string like '30d', '-1', '1h', or leaving whitespace/garbage in the env; putting an invalid default in the config file.","commonSituations":"Admins assuming human-readable durations ('24h', '7d') are supported; copying Docker env examples with placeholder text; typos like 'never ' with trailing space handled, but 'expired' etc. not.","solutions":["Set TOKEN_EXPIRATION to a plain number of days (e.g. '60') — only integers/floats >= 0 are accepted.","Use the special literals 'never' or 'openid-provider' if you want no expiry / provider-controlled expiry.","Convert duration expressions yourself: '30d' -> '30'.","Check for stray quotes, spaces, or CR characters in the env value if a numeric-looking value still fails."],"exampleFix":"// before\nTOKEN_EXPIRATION=30d      // throws 'Invalid token_expiration value: 30d'\n// after\nTOKEN_EXPIRATION=30","handlingStrategy":"validation","validationCode":"const raw = process.env.TOKEN_EXPIRATION;\nconst isValid = raw === undefined || raw === 'never' || raw === 'openid-provider' ||\n  (Number.isFinite(Number(raw)) && Number(raw) >= 0);\nif (!isValid) throw new Error(`TOKEN_EXPIRATION=\"${raw}\" is invalid; use a non-negative number, 'never', or 'openid-provider'`);","typeGuard":"function isTokenExpiration(v: unknown): v is 'never' | 'openid-provider' | number {\n  if (v === 'never' || v === 'openid-provider') return true;\n  if (typeof v === 'number') return Number.isFinite(v) && v >= 0;\n  if (typeof v === 'string') { const n = Number(v); return Number.isFinite(n) && n >= 0; }\n  return false;\n}","tryCatchPattern":"try {\n  const config = loadConfig(configDir);\n  startServer(config);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Invalid token_expiration')) {\n    console.error('Fix TOKEN_EXPIRATION env var: number of days, or never/openid-provider');\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Only use plain numbers, 'never', or 'openid-provider' for TOKEN_EXPIRATION.","Never write durations like '30d' or '1h' into the env var.","Validate env vars in CI or a startup wrapper before launching the server.","Check the official docs/example .env for accepted formats."],"tags":["config","startup","validation","env-var"],"backgroundTag":"invalid-config-value","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}