{"record":{"id":"e5c07bab02d04f14","repo":"thedotmack/claude-mem","slug":"http-error","errorCode":"http_error","errorMessage":"Server ${method} ${path} returned ${response.status}: ${truncate(text, 200)}","messagePattern":"Server (.+?) (.+?) returned (.+?): (.+?)","errorType":"exception","errorClass":"ServerClientError","httpStatus":null,"severity":"error","filePath":"src/services/hooks/server-client.ts","lineNumber":390,"sourceCode":"      init.body = JSON.stringify(body);\n    }\n\n    let response: Response;\n    try {\n      response = await fetchWithTimeout(url, init, this.timeoutMs);\n    } catch (error: unknown) {\n      const message = error instanceof Error ? error.message : String(error);\n      const isTimeout = /timed out|timeout/i.test(message);\n      throw new ServerClientError(\n        isTimeout ? 'timeout' : 'transport',\n        `Server ${method} ${path} failed: ${message}`,\n        { cause: error },\n      );\n    }\n\n    if (!response.ok) {\n      const text = await response.text().catch(() => '');\n      throw new ServerClientError(\n        'http_error',\n        `Server ${method} ${path} returned ${response.status}: ${truncate(text, 200)}`,\n        { status: response.status },\n      );\n    }\n\n    const text = await response.text();\n    if (!text || text.length === 0) {\n      // Endpoints we call always return JSON; a body-less success is unusual\n      // but not fatal — return undefined-shaped object.\n      return {} as T;\n    }\n    try {\n      return JSON.parse(text) as T;\n    } catch (error: unknown) {\n      const err = error instanceof Error ? error : new Error(String(error));\n      throw new ServerClientError(\n        'invalid_response',","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/hooks/server-client.ts#L372-L408","documentation":"Thrown when the server responded, but with a non-2xx status. The response body (truncated to 200 chars) is embedded in the message and the HTTP status is attached to the error. Code is 'http_error'. This surfaces server-side rejections such as 401 unauthorized, 404 unknown route, or 500 internal errors.","triggerScenarios":"Any ServerClient request where response.ok is false — e.g. revoked/wrong API key (401), hitting a server version lacking the endpoint (404), or a server-side exception (5xx).","commonSituations":"API key rotated or invalid, client and server version mismatch after an upgrade, or the server crashing while handling a malformed payload.","solutions":["Read the status and body in the message: 401/403 → fix CLAUDE_MEM_SERVER_API_KEY; 404 → align client and server versions.","For 5xx, check server logs for the underlying exception and retry after fixing.","Handle the error by inspecting err.status for programmatic branching (e.g. skip on 404).","Re-run the server upgrade if the endpoint was added in a newer version."],"exampleFix":"// before\nawait client.recordEvent(event); // throws http_error 404\n\n// after\ntry {\n  await client.recordEvent(event);\n} catch (e) {\n  if (e instanceof ServerClientError && e.code === 'http_error' && e.status === 404) {\n    // fall back to local processing; server does not support this endpoint\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await client.searchObservations(q);\n} catch (e) {\n  if (e instanceof ServerClientError && e.code === 'http_error') {\n    switch (e.status) {\n      case 401: case 403: /* refresh API key */ break;\n      case 404: /* fall back to local mode */ break;\n      default: /* log and retry later */\n    }\n  } throw e;\n}","preventionTips":["Keep client and server versions aligned to avoid 404s on newer endpoints.","Rotate API keys on both sides together to avoid 401s.","Watch server logs when you see 5xx statuses in client errors."],"tags":["http","api","server-response"],"backgroundTag":"http-error-response","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}