{"record":{"id":"8cee42bc6ef9b403","repo":"mastra-ai/mastra","slug":"a-custom-capture-schema-requires-an-onextracted-ho","errorCode":null,"errorMessage":"A custom capture schema requires an onExtracted hook that handles its output.","messagePattern":"A custom capture schema requires an onExtracted hook that handles its output\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/memory/src/processors/observational-memory/subconscious/index.ts","lineNumber":208,"sourceCode":"  }\n\n  #validateObservationEntry(entry: SubconsciousObservationEntry): void {\n    const name = entryName(entry);\n    if (typeof entry === 'string') {\n      if (!BUILT_IN_OBSERVATION.has(name)) throw new Error(`Unknown Subconscious observation agent: ${name}`);\n      return;\n    }\n    if (BUILT_IN_OBSERVATION.has(name)) {\n      if (name === 'capture') {\n        if ('model' in entry || 'maxSteps' in entry) {\n          throw new Error('Subconscious capture shares the Observer model and does not accept model or maxSteps.');\n        }\n        if (\n          'schema' in entry &&\n          entry.schema &&\n          (!('onExtracted' in entry) || typeof entry.onExtracted !== 'function')\n        ) {\n          throw new Error('A custom capture schema requires an onExtracted hook that handles its output.');\n        }\n      }\n      return;\n    }\n    if ('model' in entry || 'maxSteps' in entry) {\n      throw new Error(\n        `Subconscious observation extractor \"${name}\" shares the Observer model and does not accept model or maxSteps.`,\n      );\n    }\n    if (!('schema' in entry) || !entry.schema || !('onExtracted' in entry) || typeof entry.onExtracted !== 'function') {\n      throw new Error(`Custom Subconscious observation agent \"${name}\" requires schema and onExtracted.`);\n    }\n  }\n\n  #validateReflectionEntry(entry: SubconsciousReflectionEntry): void {\n    const name = entryName(entry);\n    if (typeof entry === 'string') {\n      if (!BUILT_IN_REFLECTION.has(name)) throw new Error(`Unknown Subconscious reflection agent: ${name}`);","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/subconscious/index.ts#L190-L226","documentation":"A capture entry may declare a custom output schema, but a schema alone is unusable: the library requires an onExtracted callback that knows how to handle the schema's output. If entry.schema is set/truthy and onExtracted is missing or not a function, the constructor throws.","triggerScenarios":"new Subconscious({ observation: [{ name: 'capture', schema: ZodSchema }] }) with no onExtracted, or onExtracted set to a non-function (e.g. undefined, a string).","commonSituations":"Adding a schema to constrain capture output but forgetting the handler; passing onExtracted: undefined via spread config; typos like onExtract or onextracted.","solutions":["Add an onExtracted: async (result, ctx) => {...} function to the capture entry.","Remove the schema if you want default capture behavior with no custom hook.","Fix the property name/spelling so onExtracted is actually a function."],"exampleFix":"// before\n{ name: 'capture', schema: InsightSchema }\n// after\n{ name: 'capture', schema: InsightSchema, onExtracted: async (insight) => { await save(insight); } }","handlingStrategy":"validation","validationCode":"function captureEntryIsValid(e: { schema?: unknown; onExtracted?: unknown }): boolean {\n  return !e.schema || typeof e.onExtracted === 'function';\n}\nif (!captureEntryIsValid(myCapture)) throw new Error('schema requires onExtracted');","typeGuard":"function hasOnExtracted<T extends { onExtracted?: unknown }>(e: T): e is T & { onExtracted: (r: unknown) => Promise<void> | void } {\n  return typeof e.onExtracted === 'function';\n}","tryCatchPattern":"try {\n  sub = new Subconscious({ observation: [entry] });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('onExtracted hook')) {\n    console.error('capture schema provided without onExtracted handler');\n  } else throw e;\n}","preventionTips":["Always pair schema with onExtracted in a single factory helper.","Type your capture entry so onExtracted is required when schema is present.","Unit-test construction with your real config."],"tags":["configuration","validation","schema"],"backgroundTag":"missing-required-callback","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}