{"record":{"id":"7f073d76a0937f54","repo":"ruvnet/ruflo","slug":"user-token-not-found","errorCode":null,"errorMessage":"User token not found","messagePattern":"User token not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ruflo/src/ruvocal/src/lib/server/apiToken.ts","lineNumber":6,"sourceCode":"import { config } from \"$lib/server/config\";\n\nexport function getApiToken(locals: App.Locals | undefined) {\n\tif (config.USE_USER_TOKEN === \"true\") {\n\t\tif (!locals?.token) {\n\t\t\tthrow new Error(\"User token not found\");\n\t\t}\n\t\treturn locals.token;\n\t}\n\treturn config.OPENAI_API_KEY || config.HF_TOKEN;\n}\n","sourceCodeStart":1,"sourceCodeEnd":12,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/ruflo/src/ruvocal/src/lib/server/apiToken.ts#L1-L12","documentation":"Thrown by getApiToken when config.USE_USER_TOKEN === 'true' but the request's locals.token is missing. In per-user-token mode the app intentionally uses each visitor's own token instead of a shared server key, so a missing per-user token is a hard failure rather than a silent fallback.","triggerScenarios":"USE_USER_TOKEN is enabled (string 'true') and getApiToken(locals) is called with locals undefined or locals.token absent — e.g. a code path that runs before the auth middleware populates locals, a background job with no request context, or a test that does not stub locals.","commonSituations":"Enabling USE_USER_TOKEN without ensuring every inference code path has the auth middleware upstream; a cron/queue worker reusing a function that calls getApiToken but with no HTTP request; login/session expired so locals.token was not set; typo in the env var ('True' vs 'true' — note it is a strict string compare to 'true').","solutions":["Ensure the auth middleware that sets locals.token runs before any code path calling getApiToken.","If you need server-side background inference, do not enable USE_USER_TOKEN for that path (or branch on a non-request context).","Set USE_USER_TOKEN exactly to the string 'true' if you intend it on, or unset/false otherwise.","For tests, pass a stub locals object: getApiToken({ token: 'test-token' })."],"exampleFix":"// before\nconst token = getApiToken(locals); // throws in a worker with no locals\n\n// after\nif (config.USE_USER_TOKEN === 'true' && !locals?.token) {\n  throw new Error('per-user token required but none on request — is auth middleware upstream?');\n}\nconst token = getApiToken(locals);","handlingStrategy":"validation","validationCode":"function getApiTokenSafe(locals?: App.Locals): string {\n  if (config.USE_USER_TOKEN === 'true') {\n    if (!locals?.token) throw new Error('per-user token required but none on request — is auth middleware upstream?');\n    return locals.token;\n  }\n  return config.OPENAI_API_KEY || config.HF_TOKEN;\n}","typeGuard":"function hasUserToken(locals: App.Locals | undefined): locals is App.Locals & { token: string } { return !!locals?.token; }","tryCatchPattern":"try { return getApiToken(locals); } catch (e) { if ((e as Error).message === 'User token not found') throw new Error('Login required', { cause: e }); throw e; }","preventionTips":["Set USE_USER_TOKEN exactly to 'true' only if every inference path has auth middleware upstream.","Branch background workers off getApiToken.","Stub locals.token in tests."],"tags":["auth","config","token","ruvocal"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}