thedotmack/claude-mem · error
generation parse error: ${outcome.reason}
Error message
generation parse error: ${outcome.reason} What it means
Thrown by ProviderObservationGenerator when the generation outcome has kind 'parse_error' — the model returned content that could not be parsed into observations (processGeneratedResponse/processSessionSummaryResponse). Before throwing, it calls markGenerationFailed with classification 'parse_error' and retryable:false, so the job is permanently marked failed rather than requeued. The outcome.reason is included in the message.
Source
Thrown at src/server/generation/ProviderObservationGenerator.ts:262
apiKeyId: payload.api_key_id,
actorId: payload.actor_id,
sourceAdapter: payload.source_adapter,
...(this.options.workerId !== undefined ? { workerId: this.options.workerId } : {}),
};
const outcome: ProcessGeneratedResponseOutcome = fresh.sourceType === 'session_summary'
? await processSessionSummaryResponse(persistInput)
: await processGeneratedResponse(persistInput);
if (outcome.kind === 'parse_error') {
await markGenerationFailed({
pool: this.options.pool,
job: fresh,
reason: outcome.reason,
classification: 'parse_error',
retryable: false,
...(this.options.workerId !== undefined ? { workerId: this.options.workerId } : {}),
});
throw new Error(`generation parse error: ${outcome.reason}`);
}
logger.info('SYSTEM', 'generation completed', {
correlationId,
jobId: outcome.jobId,
bullmqJobId: job.id ?? null,
requestId: payloadRequestId,
observationCount: outcome.observations.length,
privateContentDetected: outcome.privateContentDetected,
});
return {
jobId: outcome.jobId,
status: 'completed',
observationCount: outcome.observations.length,
};
}
View on GitHub (pinned to d768ba3643)
Solutions
- Inspect outcome.reason in the message and the stored failed-job record to see the exact parse failure and any raw model output captured.
- Raise maxOutputTokens for the provider so the response isn't truncated.
- Retry the job manually if the failure was transient (a one-off malformed response).
- If a model change caused it, revert to a model known to follow the output schema, or adjust the prompt/parser.
- Check the provider's raw response (enable debug logging) to confirm whether it is truncation vs. format drift.
Example fix
// before: default token cap truncates large session output
new ClaudeObservationProvider({ apiKey, model });
// after: raise the cap so JSON isn't cut mid-object
new ClaudeObservationProvider({ apiKey, model, maxOutputTokens: 8192 }); Defensive patterns
Strategy: try-catch
Validate before calling
// Before submitting the job, sanity-check token budget vs. session size.
function estimateMaxTokensForSession(obsCharCount: number): number {
// rough: ~4 chars/token; ensure headroom for JSON envelope
const needed = Math.ceil(obsCharCount / 4) + 1024;
return Math.max(4096, Math.min(needed, 16384));
} Try / catch
try {
await generator.process(job);
} catch (error) {
if (/generation parse error/i.test((error as Error).message)) {
// job already marked failed (retryable:false). Inspect outcome.reason from
// the stored failed-job record; optionally re-enqueue after raising
// maxOutputTokens or switching models.
await inspectFailedJob(job.id);
return;
}
throw error;
} Prevention
- Size maxOutputTokens to the session being summarized to avoid truncation mid-JSON.
- Prefer models that reliably follow structured-output instructions.
- Log the raw model output at debug level so parse failures are diagnosable.
- Treat parse_error jobs as non-retriable by default; only re-enqueue after a config/model change.
When it happens
Trigger: The LLM returned prose instead of the expected structured output; maxOutputTokens was too low and the JSON was truncated mid-object; the model emitted markdown fences or extra commentary around the JSON; a schema/prompt drift between the model and the parser; an unexpected provider response shape.
Common situations: Switching to a smaller/cheaper model that ignores output-format instructions. maxOutputTokens left at default (4096) for a large session that needs more. A provider A/B change in output formatting. A session summary path expecting a different envelope.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- CLAUDE_MEM_QUEUE_ENGINE is not "bullmq"
- parse_error
- parse_error
- parse_error
- Invalid CLAUDE_MEM_QUEUE_ENGINE=${raw}; expected sqlite or b
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/aa13888af9876f9c.
Report an issue: GitHub.