mastra-ai/mastra · error
Observer produced degenerate output after retry. ${describeD
Error message
Observer produced degenerate output after retry. ${describeDegenerateOutput(result.text)} What it means
In `ObserverRunner.call`, the Observer model's text output is parsed by `parseObserverOutput`, which flags degenerate output (pathological repetition loops common to small/local LLMs). If the first attempt is degenerate the runner retries the generation once; if the retry is also degenerate it throws this error (observer-runner.ts:314), failing the observation step rather than persisting garbage observations.
Source
Thrown at packages/memory/src/processors/observational-memory/observer-runner.ts:314
);
};
let result = await doGenerate();
let parsed = parseObserverOutput(result.text, activeExtractors);
let retriedDueToDegenerate = false;
if (parsed.degenerate) {
omDebug(
`[OM:callObserver] degenerate repetition detected, retrying once. ${describeDegenerateOutput(result.text, 2000)}`,
);
result = await doGenerate();
parsed = parseObserverOutput(result.text, activeExtractors);
retriedDueToDegenerate = true;
if (parsed.degenerate) {
omDebug(
`[OM:callObserver] degenerate repetition on retry, failing. ${describeDegenerateOutput(result.text, 2000)}`,
);
throw new Error(`Observer produced degenerate output after retry. ${describeDegenerateOutput(result.text)}`);
}
}
const structuredExtraction = await extractStructuredValues({
agent,
source: 'observer',
extractors: activeExtractors,
memory: temporaryMemory?.options,
priorExtractedValues: options?.priorExtractedValues,
requestContext: internalRequestContext,
observabilityContext: options?.observabilityContext,
abortSignal,
});
const extractedValues = mergeExtractedValues(parsed.extractedValues, structuredExtraction.values);
const extractionFailures = mergeExtractionFailures(parsed.extractionFailures, structuredExtraction.failures);
const builtIns = getBuiltInExtractedValues(extractedValues);
const systemPrompt = buildObserverSystemPrompt(View on GitHub (pinned to 75dd419e61)
Solutions
- Use a stronger observation model: set `observationModel` in the ObservationalMemory processor config to a capable model (e.g. 'openai/gpt-4o-mini' or similar) instead of a small local model.
- Tune `modelSettings` for the observer — add a `repetitionPenalty`/`frequencyPenalty` or raise temperature slightly so the model breaks out of loops.
- Check whether the observer prompt/context is being truncated (huge threads); reduce thread size or enable earlier observation cycles so the prompt stays small.
- Retry the overall operation later (transient provider degradation) or add a fallback observation model; inspect `describeDegenerateOutput` in the error text to see the repetition pattern.
Example fix
// before
new ObservationalMemory({
observationModel: 'ollama/llama3.2:1b', // degenerates on structured prompts
});
// after
new ObservationalMemory({
observationModel: 'openai/gpt-4o-mini',
modelSettings: { temperature: 0.3, frequencyPenalty: 0.5 },
}); Defensive patterns
Strategy: fallback
Validate before calling
// sanity-check the observation model before wiring it in
const resp = await model.doGenerate({
prompt: [{ role: 'user', content: [{ type: 'text', text: 'Reply with the word: OK' }] }],
});
if (new Set(resp.text.split(/\s+/)).size < 3 && resp.text.length > 200) {
throw new Error('observation model appears prone to repetition; choose a stronger model');
} Type guard
function looksDegenerate(text: string): boolean {
const lines = text.split('\n').map(l => l.trim()).filter(Boolean);
if (lines.length < 4) return false;
const unique = new Set(lines);
return unique.size / lines.length < 0.5; // >50% duplicate lines
} Try / catch
try {
await memory.process(messages, { abortSignal: signal });
} catch (err) {
if (err instanceof Error && err.message.startsWith('Observer produced degenerate output')) {
logger.warn('observer model looping; switching to fallback model');
await memoryWithFallbackModel.process(messages, { abortSignal: signal });
return;
}
throw err;
} Prevention
- Use a capable instruction-tuned model as observationModel; avoid sub-3B/quantized models for observer duties.
- Set frequencyPenalty/repetitionPenalty and moderate temperature in observer modelSettings.
- Keep observer prompts small: observe frequently so each cycle sees few messages.
- Verify context-window size of the observation model exceeds your largest thread batch.
When it happens
Trigger: The configured observation model produces a repetition loop (e.g. repeated observation blocks or tokens) in the Observer prompt, and after one automatic retry (`doGenerate()` again) still produces degenerate output. Typically triggered by weak/quantized local models (small Ollama models, unstable fine-tunes) or too-high temperature/maxTokens settings for the observer.
Common situations: Using a tiny local model (e.g. 1-3B quantized) as `observationModel` which loops on the structured observer prompt; a provider outage returning filler/repetitive text; prompt overflow causing truncated/degenerate completion; model settings (temperature too low for structured output, or repetition penalties unset) producing loops.
Related errors
- Multi-thread observer produced degenerate output after retry
- Extractor "${extractor.slug}" output did not match its schem
- ${EXTRACTED_VALUES_TAG} must contain a JSON object.
- Curator did not acknowledge a valid processed KnowledgeRecor
- Learner did not acknowledge a valid reviewed record cursor.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/b3b3b75091bca92b.
Report an issue: GitHub.