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

  1. 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.
  2. Tune `modelSettings` for the observer — add a `repetitionPenalty`/`frequencyPenalty` or raise temperature slightly so the model breaks out of loops.
  3. Check whether the observer prompt/context is being truncated (huge threads); reduce thread size or enable earlier observation cycles so the prompt stays small.
  4. 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

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/b3b3b75091bca92b. Report an issue: GitHub.