{"record":{"id":"3fb1107f36ca7c0b","repo":"thedotmack/claude-mem","slug":"unauthorized","errorCode":"Unauthorized","errorMessage":"Missing API key (Authorization: Bearer <key> or X-Api-Key: <key>)","messagePattern":"Missing API key \\(Authorization: Bearer <key> or X-Api-Key: <key>\\)","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"src/server/middleware/auth.ts","lineNumber":71,"sourceCode":"      && isLocalhost(req)\n      && hasLoopbackHostHeader(req)\n      && !hasForwardedClientHeaders(req)\n    ) {\n      req.authContext = {\n        userId: null,\n        organizationId: null,\n        teamId: null,\n        projectId: null,\n        scopes: ['local-dev'],\n        apiKeyId: null,\n        mode: 'local-dev',\n      };\n      next();\n      return;\n    }\n\n    if (!rawKey) {\n      res.status(401).json({\n        error: 'Unauthorized',\n        message: 'Missing API key (Authorization: Bearer <key> or X-Api-Key: <key>)',\n      });\n      return;\n    }\n\n    const verified = verifyServerApiKey(getDatabase(), rawKey, options.requiredScopes ?? []);\n    if (!verified) {\n      res.status(403).json({ error: 'Forbidden', message: 'Invalid API key or insufficient scope' });\n      return;\n    }\n\n    req.authContext = {\n      userId: null,\n      organizationId: null,\n      teamId: verified.teamId,\n      projectId: verified.projectId,\n      scopes: verified.scopes,","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/server/middleware/auth.ts#L53-L89","documentation":"401 from the SQLite auth middleware when the request carries no API key at all. The middleware extracts the key from Authorization: Bearer <key> or X-Api-Key: <key>; when local-dev mode is disabled and rawKey is empty, it rejects immediately with this message documenting both accepted header forms.","triggerScenarios":"Any request to a protected route (e.g. POST /api/sessions/summarize) with neither Authorization nor X-Api-Key header; header name typo like X-API-Key with wrong casing in a raw client (case-insensitive in HTTP, but misspelled names fail); env var holding the key is unset so the client sends 'Bearer undefined'.","commonSituations":"Forgot to set API_KEY in .env so the client sends an empty/undefined token; curl invocation missing -H; switching a script from local-dev (where no key is needed) to a deployed server where local-dev is off.","solutions":["Send the key in one of the two accepted headers: Authorization: Bearer <key> or X-Api-Key: <key>.","Check the environment variable that carries the key is actually set in the client's environment (print its presence, never its value).","If you intended to run without keys, enable the server's local-dev mode — but never in production.","Verify the header name spelling and that no proxy strips Authorization on its way to the server."],"exampleFix":"# before\ncurl -X POST https://host/api/sessions/summarize -d '{}'\n// 401 Missing API key\n\n# after\ncurl -X POST https://host/api/sessions/summarize \\\n  -H 'Authorization: Bearer sk-...' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"contentSessionId\":\"...\"}'","handlingStrategy":"validation","validationCode":"function buildHeaders(key: string | undefined): Record<string, string> {\n  if (!key) throw new Error('API key is not configured (set API_KEY)');\n  return { 'X-Api-Key': key, 'Content-Type': 'application/json' };\n}","typeGuard":"interface UnauthorizedBody { error: string; message: string }\nfunction isMissingApiKey(body: unknown): body is UnauthorizedBody {\n  return typeof body === 'object' && body !== null &&\n    (body as UnauthorizedBody).error === 'Unauthorized' &&\n    (body as UnauthorizedBody).message?.startsWith('Missing API key');\n}","tryCatchPattern":null,"preventionTips":["Fail fast at startup when the key env var is unset rather than on first request.","Centralize auth header construction in one client wrapper.","Assert the key is non-empty and not the literal 'undefined'."],"tags":["auth","http-401","api-key","middleware"],"backgroundTag":"missing-api-key","analyzedSha":"e2d1df569a8f04075d40e92461128ece7cf04c82","analyzedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}