{"record":{"id":"c96bdc7f34633026","repo":"mastra-ai/mastra","slug":"extractor-name-must-include-instructions","errorCode":null,"errorMessage":"Extractor \"${name}\" must include instructions.","messagePattern":"Extractor \"(.+?)\" must include instructions\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/memory/src/processors/observational-memory/extractor.ts","lineNumber":149,"sourceCode":"  readonly metadataKeyPath: string | false;\n  readonly onExtracted?: ExtractorConfig<T>['onExtracted'];\n  readonly retryStructuredExtractionOnEmptyObject: boolean;\n  /** @internal */\n  readonly internal: boolean;\n  private readonly instructionsConfig: ExtractorConfigValue<string>;\n  private readonly schemaConfig?: ExtractorConfigValue<z.ZodType<T> | undefined>;\n\n  constructor(config: ExtractorConfig<T>, internal = false) {\n    const name = config.name.trim();\n    const instructions = typeof config.instructions === 'string' ? config.instructions.trim() : undefined;\n    const slug = slugifyExtractorName(name);\n    const isHook = config.mode === 'hook';\n\n    if (!name) {\n      throw new Error('Extractor name is required.');\n    }\n    if (!isHook && !config.instructions) {\n      throw new Error(`Extractor \"${name}\" must include instructions.`);\n    }\n    if (instructions !== undefined && !instructions) {\n      throw new Error(`Extractor \"${name}\" must include instructions.`);\n    }\n    if (isHook && !config.onExtracted) {\n      throw new Error(`Hook extractor \"${name}\" must include an onExtracted handler.`);\n    }\n    if (isHook && (config.instructions || config.schema)) {\n      throw new Error(`Hook extractor \"${name}\" cannot include instructions or a schema.`);\n    }\n    assertValidSlug(slug, name);\n    if (!internal && RESERVED_XML_TAGS.has(slug)) {\n      throw new Error(`Extractor slug \"${slug}\" is reserved by Observational Memory.`);\n    }\n\n    this.name = name;\n    this.slug = slug;\n    this.instructionsConfig = config.instructions ?? '';","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/extractor.ts#L131-L167","documentation":"In Observational Memory, non-hook extractors contribute an instructions block to the observer/reflector prompt, so `instructions` is mandatory when constructing an `Extractor`. The library throws this error in the constructor when `mode` is not 'hook' and `config.instructions` is falsy (missing, undefined, null, or empty string). It enforces that every prompt-driven extractor describes what it should extract.","triggerScenarios":"new Extractor({ name: 'X' }) without instructions; new Extractor({ name: 'X', mode: 'inline' }) with instructions omitted; instructions passed as empty string ''; a dynamic instruction function accidentally not passed (e.g. undefined variable).","commonSituations":"Hand-writing an extractor config and forgetting the prompt text; copying a hook-mode example but leaving mode: 'hook' off; refactoring so instructions became an undefined variable; testing with a stub config.","solutions":["Add a non-empty `instructions` string describing what the extractor should return.","If the extractor should run purely as a post-processing callback, set `mode: 'hook'` and provide `onExtracted` instead.","Check that the variable holding instructions is defined and not trimmed down to an empty string before construction."],"exampleFix":"// before\nconst e = new Extractor({ name: 'User Preferences' });\n// after\nconst e = new Extractor({\n  name: 'User Preferences',\n  instructions: 'Extract durable user preferences from observations.',\n});","handlingStrategy":"validation","validationCode":"function assertExtractorConfig(config) {\n  if (config.mode !== 'hook' && !config.instructions) {\n    throw new Error(`Extractor \"${config.name}\" must include instructions.`);\n  }\n}","typeGuard":"function hasInstructions(c) { return typeof c.instructions === 'string' && c.instructions.trim().length > 0; }","tryCatchPattern":"try {\n  const extractor = new Extractor(config);\n} catch (e) {\n  if (e.message.includes('must include instructions')) {\n    logger.error('Extractor misconfigured: missing instructions', { name: config.name });\n  } else { throw e; }\n}","preventionTips":["Always pair every non-hook Extractor with explicit instructions text.","Use the TypeScript ExtractorConfig type so missing required fields surface at compile time where possible.","Lint/CI check: no `new Extractor(` call with an object literal lacking `instructions` or `mode: 'hook'`."],"tags":["config","validation","observational-memory"],"backgroundTag":"missing-required-config-option","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}