{"record":{"id":"bc6bfa90599970ef","repo":"can1357/oh-my-pi","slug":"sharpshooter-extraction-model-error","errorCode":null,"errorMessage":"Sharpshooter extraction model error","messagePattern":"Sharpshooter extraction model error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/sharpshooter/extract.ts","lineNumber":232,"sourceCode":"\tconst input = prompt.render(extractInputTemplate, { ...envelope });\n\tconst response = await retryTransientCompletion(() =>\n\t\tcompleteSimple(\n\t\t\tmodel,\n\t\t\t{\n\t\t\t\tsystemPrompt: [prompt.render(extractSystemTemplate)],\n\t\t\t\tmessages: [{ role: \"user\", content: [{ type: \"text\", text: input }], timestamp: Date.now() }],\n\t\t\t\ttools: [recordDeltasTool],\n\t\t\t},\n\t\t\t{\n\t\t\t\tapiKey: modelRegistry.resolver(model),\n\t\t\t\tmaxTokens: 2048,\n\t\t\t\treasoning: clampThinkingLevelForModel(model, Effort.Low),\n\t\t\t\ttoolChoice: \"required\",\n\t\t\t},\n\t\t),\n\t);\n\tif (response.stopReason === \"error\") {\n\t\tthrow new Error(response.errorMessage || \"Sharpshooter extraction model error\");\n\t}\n\n\tfor (const block of response.content) {\n\t\tif (block.type !== \"toolCall\" || block.name !== recordDeltasTool.name) continue;\n\t\tconst args = block.arguments;\n\t\tif (!args || typeof args !== \"object\" || !(\"deltas\" in args) || !Array.isArray(args.deltas)) {\n\t\t\tlogger.debug(\"Sharpshooter extraction rejected malformed record_deltas call\");\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const candidate of args.deltas) {\n\t\t\tconst delta = admitDelta(candidate, envelope.prompt, session.sessionId);\n\t\t\tif (!delta) continue;\n\t\t\tif (session.isDisposed) return;\n\t\t\tawait appendSharpshooterDelta(agentDir, session.sessionManager.getCwd(), delta);\n\t\t}\n\t}\n}\n","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/sharpshooter/extract.ts#L214-L250","documentation":"runSharpshooterExtraction performs an LLM call and checks the response's stopReason. When the provider reports `stopReason === \"error\"`, this error is thrown with the provider's errorMessage, or the generic fallback message if none was supplied. It signals the extraction request itself failed rather than producing tool-call output.","triggerScenarios":"API/network failure, auth rejection, rate limit, content filter, or provider 5xx during the sharpshooter extraction completion — anything the client maps to stopReason \"error\".","commonSituations":"Expired or missing API key; provider outage; context window exceeded by a huge session; rate limiting during batch consolidation.","solutions":["Inspect response.errorMessage (it is embedded in the thrown message when present) for the provider's actual cause.","Verify provider credentials and quota for the extraction model.","Retry with backoff if the message indicates a transient (429/5xx) failure.","Reduce session size if the request exceeded context limits."],"exampleFix":"// handle extraction failure gracefully\ntry {\n  await runSharpshooterExtraction(...);\n} catch (err) {\n  logger.warn(\"sharpshooter extraction failed; keeping existing memory\", { err });\n}","handlingStrategy":"try-catch","validationCode":"if (!process.env.API_KEY) throw new Error(\"extraction model credentials missing before run\");","typeGuard":"null","tryCatchPattern":"try {\n  await runSharpshooterExtraction(session);\n} catch (err) {\n  logger.warn(\"sharpshooter extraction failed\", { err });\n  // fall back to keeping existing memory files\n}","preventionTips":["Validate provider API keys and quota before long runs.","Retry with exponential backoff on transient provider errors.","Keep session context within the extraction model's window.","Monitor provider status pages during batch jobs."],"tags":["network","llm-provider","api-error"],"backgroundTag":"llm-request-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}