{"record":{"id":"64a333afb3549e60","repo":"mastra-ai/mastra","slug":"the-operation-was-aborted","errorCode":null,"errorMessage":"The operation was aborted.","messagePattern":"The operation was aborted\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/memory/src/processors/observational-memory/observer-runner.ts","lineNumber":185,"sourceCode":"   * the provider capabilities registry is consulted to decide whether the\n   * model accepts multimodal input.\n   */\n  private resolveAttachmentFilter(\n    model: ConcreteObservationModel,\n    requestContext?: RequestContext,\n  ): ObserverAttachmentFilter {\n    const raw = this.observationConfig.observeAttachments;\n    if (raw !== 'auto') return raw;\n\n    const routerId = this.extractModelRouterId(model, requestContext);\n    if (!routerId) return true; // can't determine — default to forwarding\n    const supports = modelSupportsAttachments(routerId);\n    return supports ?? true;\n  }\n\n  private async withAbortCheck<T>(fn: () => Promise<T>, abortSignal?: AbortSignal): Promise<T> {\n    if (abortSignal?.aborted) {\n      throw new Error('The operation was aborted.');\n    }\n    const result = await fn();\n    if (abortSignal?.aborted) {\n      throw new Error('The operation was aborted.');\n    }\n    return result;\n  }\n\n  /**\n   * Call the Observer agent for a single thread.\n   */\n  async call(\n    existingObservations: string | undefined,\n    messagesToObserve: MastraDBMessage[],\n    abortSignal?: AbortSignal,\n    options?: {\n      skipContinuationHints?: boolean;\n      requestContext?: RequestContext;","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/observer-runner.ts#L167-L203","documentation":"The Observational Memory observer runner wraps the Observer agent's model call in `withAbortCheck`, which throws this plain Error when the caller-supplied `AbortSignal` is already aborted before the call starts (observer-runner.ts:185). It is the library's way of canceling observational-memory work early instead of spending tokens on a generation whose result will be discarded. It mirrors the standard DOM/AbortController cancellation contract, but is raised as a synchronous pre-flight check rather than coming from the provider.","triggerScenarios":"Calling memory retrieval/processing (e.g. via `ObservationalMemory` processor inside an agent run) with an `abortSignal` that is already in the `aborted` state when `ObserverRunner.call` -> `doGenerate` -> `withAbortCheck` runs. Typically the request that triggered memory processing was cancelled before the observer step began.","commonSituations":"A client disconnects from an HTTP request and the server aborts the controller before memory processing starts; a timeout (AbortSignal.timeout) fires before the observer call; a UI cancels a previous in-flight agent generation whose shared signal is reused for memory work; passing `req.signal` from an already-finished request.","solutions":["Check `abortSignal?.aborted` before invoking the agent/memory call and skip observer processing (return early) instead of starting work that will throw.","Ensure each agent run uses its own AbortController rather than sharing one signal across sequential operations (generation, then memory), so an abort from one phase doesn't pre-abort the next.","If you actually want the work to complete, do not pass an `abortSignal` (it is optional) or pass `AbortSignal.any([...])` excluding the cancelling source.","Catch this error in the caller and treat it as a benign cancellation (e.g. rethrow `AbortError` or log-and-return) so cancelled requests don't surface as failures."],"exampleFix":"// before\nawait agent.generate(messages, {\n  abortSignal: sharedController.signal, // already aborted by a previous cancelled request\n});\n\n// after\nif (controller.signal.aborted) {\n  return; // skip memory processing for cancelled requests\n}\nawait agent.generate(messages, {\n  abortSignal: controller.signal,\n});","handlingStrategy":"try-catch","validationCode":"if (signal?.aborted) {\n  // don't start memory processing at all\n  return skipObservation();\n}","typeGuard":"function isAborted(signal?: AbortSignal): boolean {\n  return signal?.aborted === true;\n}","tryCatchPattern":"try {\n  await memory.process(messages, { abortSignal: signal });\n} catch (err) {\n  if (err instanceof Error && err.message === 'The operation was aborted.') return; // benign cancellation\n  throw err;\n}","preventionTips":["Always check `signal.aborted` before invoking memory/agent APIs.","Use a fresh AbortController per agent run instead of sharing signals across phases.","Use `AbortSignal.any([...])` to compose only the sources you intend to cancel on.","Treat 'The operation was aborted.' as cancellation, not failure, in error handling."],"tags":["abortsignal","cancellation","observational-memory"],"backgroundTag":"operation-aborted","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}