{"record":{"id":"f99a9f43cc25d36d","repo":"can1357/oh-my-pi","slug":"operation-failed-typeof-details-string","errorCode":null,"errorMessage":"${operation} failed: ${typeof details === \"string\" ? details : JSON.stringify(details)}","messagePattern":"(.+?) failed: (.+?)","errorType":"http","errorClass":"HindsightError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/hindsight/client.ts","lineNumber":574,"sourceCode":"\t\t\tthrow new HindsightError(message, undefined, err);\n\t\t}\n\n\t\tif (opts?.allow404 && response.status === 404) {\n\t\t\treturn null as T;\n\t\t}\n\n\t\tconst text = await response.text();\n\t\tconst parsed = text ? safeJsonParse(text) : null;\n\n\t\tif (!response.ok) {\n\t\t\tconst details =\n\t\t\t\t(parsed && typeof parsed === \"object\"\n\t\t\t\t\t? ((parsed as { detail?: unknown; message?: unknown }).detail ??\n\t\t\t\t\t\t(parsed as { message?: unknown }).message)\n\t\t\t\t\t: undefined) ??\n\t\t\t\tparsed ??\n\t\t\t\ttext;\n\t\t\tthrow new HindsightError(\n\t\t\t\t`${operation} failed: ${typeof details === \"string\" ? details : JSON.stringify(details)}`,\n\t\t\t\tresponse.status,\n\t\t\t\tdetails,\n\t\t\t);\n\t\t}\n\n\t\treturn (parsed ?? {}) as T;\n\t}\n}\n\ninterface BuiltMemoryItem {\n\tcontent: string;\n\ttimestamp?: string;\n\tcontext?: string;\n\tmetadata?: Record<string, string>;\n\tdocument_id?: string;\n\ttags?: string[];\n\tobservation_scopes?: \"per_tag\" | \"combined\" | \"all_combinations\" | string[][];","sourceCodeStart":556,"sourceCodeEnd":592,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/hindsight/client.ts#L556-L592","documentation":"HindsightClient.#request converts non-OK HTTP responses into a HindsightError. It extracts a detail/message field from the parsed JSON body (or falls back to raw text) and formats `${operation} failed: <details>`, including the HTTP status code on the error object.","triggerScenarios":"Any Hindsight API call (retain, recall, reflect, createBank, listMemories) receiving a 4xx/5xx response: invalid request payload (400), auth failure (401/403), unknown bank (404 without allow404), or server error (500).","commonSituations":"Malformed retain payload rejected by server validation; expired or missing API credentials; calling an endpoint/route that doesn't exist on the deployed server version; upstream server crash.","solutions":["Read the HindsightError status and details fields — they carry the server's own explanation","Fix the request payload per the server validation message (400)","Check API credentials/auth configuration (401/403)","Verify client and server versions are compatible if the route 404s"],"exampleFix":"// before\nawait client.retain({ /* wrong shape */ });\n// after\ntry {\n  await client.retain({ content: \"...\", context: \"...\" });\n} catch (err) {\n  if (err instanceof HindsightError && err.status === 400) {\n    console.error(\"Server said:\", err.details);\n  }\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"// validate payload shape before sending\nif (typeof body.content !== \"string\" || body.content.length === 0) {\n  throw new Error(\"retain requires non-empty content\");\n}","typeGuard":"function isApiRejection(err: unknown): err is HindsightError & { status: number } {\n  return err instanceof HindsightError && typeof err.status === \"number\";\n}","tryCatchPattern":"try {\n  await client.retain(payload);\n} catch (err) {\n  if (err instanceof HindsightError && err.status) {\n    logger.error(\"Hindsight operation rejected\", { status: err.status, details: err.details });\n    if (err.status >= 500) /* retry */; else /* fix request */;\n  } else throw err;\n}","preventionTips":["Match request payloads to the server's current API version","Check auth credentials on 401/403 statuses","Surface err.details (server validation message) in logs","Handle 404 with allow404 for optional lookups"],"tags":["http","api-error","network"],"backgroundTag":"http-error-response","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}