{"record":{"id":"298e335ef5cf0253","repo":"Budibase/budibase","slug":"expected-indexed-request-ids-to-contain-only-strin","errorCode":null,"errorMessage":"Expected indexed request IDs to contain only strings","messagePattern":"Expected indexed request IDs to contain only strings","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/agentLogs/shared.ts","lineNumber":283,"sourceCode":"}\n\nexport function getSessionDocId(agentId: string, sessionId: string): string {\n  const encodedAgentId = encodeKeyPart(agentId)\n  const encodedSessionId = encodeKeyPart(sessionId)\n  return `${DocumentType.AGENT_LOG_SESSION}${SEPARATOR}${encodedAgentId}${SEPARATOR}${encodedSessionId}`\n}\n\nexport function parseIndexedRequestIds(value?: string): Set<string> {\n  if (!value) {\n    return new Set()\n  }\n\n  const parsed = JSON.parse(value)\n  if (!Array.isArray(parsed)) {\n    throw new Error(\"Expected indexed request IDs to be an array\")\n  }\n  if (parsed.some(item => typeof item !== \"string\")) {\n    throw new Error(\"Expected indexed request IDs to contain only strings\")\n  }\n\n  return new Set(parsed)\n}\n\nexport function getWorkspaceDbForEnvironment(environment: AgentLogEnvironment) {\n  if (environment === \"development\") {\n    return context.getDevWorkspaceDB()\n  }\n  if (environment === \"production\") {\n    return context.getProdWorkspaceDB()\n  }\n\n  throw new HTTPError(\"Invalid environment query\", 400)\n}\n\nexport function getLiteLLMRequestUser(\n  data: LiteLLMRequestDetail | AgentLogSessionIndexDoc","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/agentLogs/shared.ts#L265-L301","documentation":"parseIndexedRequestIds accepts a JSON array but every element must be a string request ID. If any element is a non-string (number, object, null, etc.), it throws Error(\"Expected indexed request IDs to contain only strings\") because the return value must be a Set<string>.","triggerScenarios":"The stored JSON array of indexed request IDs contains at least one non-string element, e.g. [12345], [null], or [{\"id\":\"x\"}].","commonSituations":"IDs were serialized as numbers by a previous writer; a migration or external script wrote raw LiteLLM numeric IDs; corrupted index documents from a failed write.","solutions":["Rewrite the stored array so every element is a string (String(id) on numeric IDs)","Fix the writer to serialize IDs with JSON.stringify([...ids]) where ids is a string[]","Catch the error and reindex the session's request IDs from the raw logs"],"exampleFix":"// before\nconst ids = parseIndexedRequestIds(value) // throws if [123]\n// after\nconst parsed: unknown[] = JSON.parse(value)\nconst ids = parseIndexedRequestIds(JSON.stringify(parsed.map(String)))","handlingStrategy":"type-guard","validationCode":"function isStringArray(value: unknown): value is string[] {\n  return Array.isArray(value) && value.every(item => typeof item === \"string\")\n}\nconst parsed: unknown = JSON.parse(value)\nif (!isStringArray(parsed)) {\n  // coerce or reindex before calling parseIndexedRequestIds\n  parsed = Array.isArray(parsed) ? parsed.map(String) : []\n}","typeGuard":"function isStringArray(value: unknown): value is string[] {\n  return Array.isArray(value) && value.every(item => typeof item === \"string\")\n}","tryCatchPattern":"try {\n  const ids = parseIndexedRequestIds(value)\n} catch (err) {\n  if (err instanceof Error && /only strings/.test(err.message)) {\n    // reindex the session or coerce: new Set(JSON.parse(value).map(String))\n  }\n}","preventionTips":["Store IDs as strings at write time (LiteLLM IDs can be numeric-looking)","Run a one-time migration coercing array elements to strings","Validate with isStringArray before persisting index docs"],"tags":["json-parsing","type-safety","schema-validation","agent-logs"],"backgroundTag":"unexpected-json-shape","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}