mastra-ai/mastra · error · Error

Extractor " " output did not match its schema

Error message

Extractor "${extractor.slug}" output did not match its schema: ${failures[0] ?? 'invalid value'}

What it means

`parseExtractorValue` validates the raw text extracted from an output tag against the extractor's Zod schema, trying JSON.parse first and then the plain string as candidates. If no candidate passes `schema.safeParse`, the library throws with the first Zod failure message. The result is captured in parseExtractedValues as a per-slug failure, but this underlying throw surfaces when the model output doesn't conform to the declared schema.

Solutions

  1. Loosen or correct the Zod schema so valid model outputs parse (add coercion, .catch(), optional fields, .default()).
  2. Sharpen the extractor `instructions` to specify the exact output format (e.g. 'Return only a JSON object with fields X and Y').
  3. Use a more capable model for the observer/reflector if it repeatedly fails to produce valid JSON.
  4. Handle the failure gracefully via parseExtractedValues' returned `failures` array rather than letting the throw propagate, and retry the extraction.

Example fix

// before
schema: z.object({ count: z.number() }) // model returns "{\"count\": \"3\"}"
// after
schema: z.object({ count: z.coerce.number() })
Defensive patterns

Strategy: fallback

Validate before calling

const preview = extractRawTag(output, slug);
const result = schema.safeParse(preview);
if (!result.success) logger.warn('Extractor output will fail schema', { slug, issues: result.error.issues });

Type guard

function matchesSchema(value, schema) { return schema.safeParse(value).success; }

Try / catch

const { values, failures } = parseExtractedValues(output, extractors);
for (const f of failures) {
  if (f.error.includes('did not match its schema')) {
    logger.warn('Schema mismatch, will retry extraction', { slug: f.slug });
  }
}

Prevention

When it happens

Trigger: Structured extractor's schema expects a number/object but the model emitted prose; JSON in the tag is valid JSON but wrong shape (missing fields, string instead of number); the model wrapped the value in markdown fences or extra text inside the tag; inline `<slug>` tag content that is a plain string but schema requires an object.

Common situations: Small/weak models ignoring JSON formatting instructions; schema too strict (e.g. .url(), enum, min length) for what the model produces; changing a schema after deployment while persisted/old outputs use the old shape; nested quotes breaking JSON.parse.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at packages/memory/src/processors/observational-memory/extractor.ts:276

      add(JSON.parse(trimmed));
    } catch {
      // Plain strings are valid extractor values.
    }
  }

  return candidates;
}

export function parseExtractorValue<T>(extractor: Extractor<T>, raw: string): T {
  const failures: string[] = [];
  for (const candidate of candidateValues(raw)) {
    const parsed = extractor.schema.safeParse(candidate);
    if (parsed.success) {
      return parsed.data;
    }
    failures.push(parsed.error.message);
  }
  throw new Error(`Extractor "${extractor.slug}" output did not match its schema: ${failures[0] ?? 'invalid value'}`);
}

export interface ParsedExtractedValues {
  values: Record<string, unknown>;
  failures: Array<{ slug: string; error: string }>;
}

function parseExtractedValuesObject(raw: string): Record<string, unknown> | undefined {
  const trimmed = raw.trim();
  if (!trimmed || trimmed.startsWith('Write only the extracted values JSON object here.')) {
    return undefined;
  }

  const parsed = JSON.parse(trimmed) as unknown;
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
    throw new Error(`${EXTRACTED_VALUES_TAG} must contain a JSON object.`);
  }
  return parsed as Record<string, unknown>;

View on GitHub (pinned to 75dd419e61)