mastra-ai/mastra · error · Error
Custom Subconscious observation agent "${name}" requires sch
Error message
Custom Subconscious observation agent "${name}" requires schema and onExtracted. What it means
A custom observation extractor must be fully specified: it needs a schema describing what to extract and an onExtracted function to consume the result. If either is missing, falsy, or onExtracted is not a function, the constructor throws. Strings are reserved for built-in agents, so custom names must be objects.
Source
Thrown at packages/memory/src/processors/observational-memory/subconscious/index.ts:219
throw new Error('Subconscious capture shares the Observer model and does not accept model or maxSteps.');
}
if (
'schema' in entry &&
entry.schema &&
(!('onExtracted' in entry) || typeof entry.onExtracted !== 'function')
) {
throw new Error('A custom capture schema requires an onExtracted hook that handles its output.');
}
}
return;
}
if ('model' in entry || 'maxSteps' in entry) {
throw new Error(
`Subconscious observation extractor "${name}" shares the Observer model and does not accept model or maxSteps.`,
);
}
if (!('schema' in entry) || !entry.schema || !('onExtracted' in entry) || typeof entry.onExtracted !== 'function') {
throw new Error(`Custom Subconscious observation agent "${name}" requires schema and onExtracted.`);
}
}
#validateReflectionEntry(entry: SubconsciousReflectionEntry): void {
const name = entryName(entry);
if (typeof entry === 'string') {
if (!BUILT_IN_REFLECTION.has(name)) throw new Error(`Unknown Subconscious reflection agent: ${name}`);
return;
}
if (BUILT_IN_REFLECTION.has(name) && 'agent' in entry && entry.agent) {
throw new Error(`Built-in Subconscious reflection agent "${name}" cannot be replaced with a custom agent.`);
}
if (!BUILT_IN_REFLECTION.has(name) && !entry.instructions?.trim() && !('agent' in entry && entry.agent)) {
throw new Error(`Custom Subconscious reflection agent "${name}" requires instructions or agent.`);
}
}
}
View on GitHub (pinned to 75dd419e61)
Solutions
- Provide both schema (a Zod/JSON schema) and onExtracted (a function) on the entry object.
- If you meant a built-in agent, use its exact built-in string name instead.
- Verify the schema is truthy and onExtracted is typeof 'function' after any config spreading/merging.
Example fix
// before
new Subconscious({ observation: [{ name: 'preferences' }] });
// after
new Subconscious({ observation: [{ name: 'preferences', schema: PrefsSchema, onExtracted: async (p) => store(p) }] }); Defensive patterns
Strategy: validation
Validate before calling
function customExtractorIsValid(e: { schema?: unknown; onExtracted?: unknown }): boolean {
return !!e.schema && typeof e.onExtracted === 'function';
}
if (!customExtractorIsValid(myExtractor)) throw new Error('custom extractor needs schema + onExtracted'); Type guard
function isCompleteExtractor(e: unknown): e is { name: string; schema: unknown; onExtracted: (r: unknown) => unknown } {
const o = e as Record<string, unknown> | null;
return !!o && !!o.schema && typeof o.onExtracted === 'function';
} Try / catch
try {
sub = new Subconscious({ observation: [entry] });
} catch (e) {
if (e instanceof Error && e.message.includes('requires schema and onExtracted')) {
console.error('Extractor entry is incomplete');
} else throw e;
} Prevention
- Never pass bare custom names as strings; strings are built-ins only.
- Build extractors via a typed helper that enforces schema + onExtracted.
- Watch for spread/merge operations dropping fields.
- Add a construction smoke test per extractor.
When it happens
Trigger: new Subconscious({ observation: [{ name: 'my-agent' }] }) (no schema/onExtracted), or { name: 'my-agent', schema: null, onExtracted: 'notAFunction' }.
Common situations: Passing just a name expecting the library to infer behavior; spreading partial config where schema/onExtracted end up undefined; using a custom name as a string (custom names are never valid strings).
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- A custom capture schema requires an onExtracted hook that ha
- Google RBAC roleMapping is required.
- Cookie password must be at least 32 characters. Set OKTA_COO
- heartbeatMs must be a finite number no greater than ${MAX_TI
- Expected a PEM-encoded public key or certificate string for
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e432e5463ca841af.
Report an issue: GitHub.