{"record":{"id":"ebed251c32451ee3","repo":"mastra-ai/mastra","slug":"extractor-this-name-must-include-instructions","errorCode":null,"errorMessage":"Extractor \"${this.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":191,"sourceCode":"    this.mode = isHook ? 'hook' : internal || !config.schema ? 'inline' : 'structured';\n    this.includePreviousExtraction = isHook ? false : (config.includePreviousExtraction ?? true);\n    this.metadataKeyPath = isHook ? false : (config.metadataKeyPath ?? `extracted.${slug}`);\n    this.onExtracted = config.onExtracted;\n    this.retryStructuredExtractionOnEmptyObject = config.retryStructuredExtractionOnEmptyObject ?? false;\n    this.internal = internal;\n  }\n\n  async resolve(context: ExtractorRuntimeContext): Promise<Extractor<T>> {\n    if (this.mode === 'hook') {\n      return this;\n    }\n\n    const instructions =\n      typeof this.instructionsConfig === 'function'\n        ? (await this.instructionsConfig(context)).trim()\n        : this.instructionsConfig.trim();\n    if (!instructions) {\n      throw new Error(`Extractor \"${this.name}\" must include instructions.`);\n    }\n\n    const schema = typeof this.schemaConfig === 'function' ? await this.schemaConfig(context) : this.schemaConfig;\n    return new Extractor(\n      {\n        name: this.name,\n        instructions,\n        ...(schema ? { schema } : {}),\n        includePreviousExtraction: this.includePreviousExtraction,\n        metadataKeyPath: this.metadataKeyPath,\n        onExtracted: this.onExtracted,\n        retryStructuredExtractionOnEmptyObject: this.retryStructuredExtractionOnEmptyObject,\n      },\n      this.internal,\n    );\n  }\n}\n","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/extractor.ts#L173-L209","documentation":"`Extractor.resolve()` re-evaluates dynamic (function-valued) `instructions` at runtime for each extraction pass, using the ProcessorContext. This mirrors the constructor guard: if the resolved instructions — including the result of calling the configured function — trim to an empty string, extraction cannot proceed and the error is thrown. This catches dynamic instruction providers that return blank content for a given context.","triggerScenarios":"instructions provided as a function that returns '' or whitespace for the current context (e.g. empty RequestContext, missing requestContext value used in a template); a non-hook extractor whose static instructionsConfig is '' — possible when the Extractor was built internally or via resolve() re-construction paths.","commonSituations":"Instructions built from requestContext/memory values that are absent at runtime; async function returning an empty template; environment-dependent prompt data not available in a worker/edge deployment.","solutions":["Make the instruction function return a non-empty fallback string when dynamic data is missing.","Validate inside the function that its inputs are present before returning.","If instructions are genuinely static, pass a plain string instead of a function to surface the error earlier (at construction)."],"exampleFix":"// before\ninstructions: async ({ requestContext }) => `Focus on ${requestContext.get('topic')}`;\n// after\ninstructions: async ({ requestContext }) => {\n  const topic = requestContext?.get('topic');\n  return topic ? `Focus on ${topic}` : 'Extract key user facts.';\n}","handlingStrategy":"validation","validationCode":"const resolved = typeof instructions === 'function' ? await instructions(context) : instructions;\nif (!resolved?.trim()) throw new Error('Dynamic instructions resolved to blank');","typeGuard":"function resolvesToInstructions(fn) { return typeof fn === 'function'; } // then validate its return value non-blank at runtime","tryCatchPattern":"try {\n  await extractor.resolve(context);\n} catch (e) {\n  if (e.message.includes('must include instructions')) {\n    logger.warn('Dynamic instructions empty for context, using fallback', { name: extractor.name });\n  } else { throw e; }\n}","preventionTips":["Always return a static fallback string from dynamic instruction functions.","Test instruction functions against contexts with missing requestContext/memory data.","Avoid building instructions purely from optional context values."],"tags":["runtime","dynamic-config","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"}