{"record":{"id":"9051b6c4cac6b973","repo":"BoundaryML/baml","slug":"operation-was-aborted","errorCode":null,"errorMessage":"Operation was aborted","messagePattern":"Operation was aborted","errorType":"exception","errorClass":"BamlAbortError","httpStatus":null,"severity":"warning","filePath":"engine/language_client_typescript/typescript_src/stream.ts","lineNumber":36,"sourceCode":"    private finalCoerce: (result: any) => FinalOutputType,\n    private ctxManager: RuntimeContextManager,\n    abortSignal?: AbortSignal,\n  ) {\n    this.abortSignal = abortSignal;\n\n    // Listen for abort to clean up\n    if (abortSignal) {\n      abortSignal.addEventListener(\"abort\", () => {\n        this.eventQueue.push(null); // Signal end of stream\n      });\n    }\n  }\n\n  private async driveToCompletion(): Promise<FunctionResult> {\n    try {\n      // Check for early abort\n      if (this.abortSignal?.aborted) {\n        throw new BamlAbortError(\n          \"Operation was aborted\",\n          this.abortSignal.reason,\n        );\n      }\n\n      this.ffiStream.onEvent(\n        (err: Error | null, data: FunctionResult | null) => {\n          if (err) {\n            this.error = err;\n            return;\n          }\n\n          this.eventQueue.push(data);\n        },\n      );\n\n      const retval = await this.ffiStream.done(this.ctxManager);\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_typescript/typescript_src/stream.ts#L18-L54","documentation":"A BamlAbortError with message 'Operation was aborted' is thrown by the stream's driveToCompletion when the AbortSignal passed to the streaming call has fired. The library checks the signal before consuming further FFI stream events and surfaces the abort as a typed error. It indicates the caller cancelled the operation, not a BAML/provider failure.","triggerScenarios":"Calling a b.stream.* function with an options.abortSignal whose .aborted becomes true (or was already true) while the result is being driven to completion.","commonSituations":"Request timeouts via AbortController.timeout(); user cancels in a UI; server request context (e.g. Next.js/Hono) aborts on client disconnect; stopping an agent loop early.","solutions":["Catch BamlAbortError separately and treat it as expected cancellation rather than a failure.","Check that you did not abort the controller prematurely (e.g. setTimeout or request teardown firing early).","If partial output is useful, consume stream events incrementally instead of only awaiting the final result.","Remove or correctly scope the abortSignal if the stream should run to completion."],"exampleFix":"// before\nconst result = await b.ExtractStory(streamOpts) // unhandled abort\n// after\ntry {\n  const result = await b.ExtractStory({ abortSignal: controller.signal })\n} catch (e) {\n  if (e instanceof BamlAbortError) return null // cancelled\n  throw e\n}","handlingStrategy":"try-catch","validationCode":"// before streaming: if (controller.signal.aborted) return null // skip the call entirely","typeGuard":null,"tryCatchPattern":"try {\n  const result = await b.ExtractStory({ abortSignal: controller.signal })\n} catch (e) {\n  if (e instanceof BamlAbortError || e.name === 'BamlAbortError') {\n    return null // expected cancellation\n  }\n  throw e\n}","preventionTips":["Only pass an abortSignal when cancellation is actually desired.","Distinguish timeouts from user cancels via the signal's reason.","Consume stream increments if partial output matters before abort."],"tags":["abort","streaming","typescript","cancellation"],"backgroundTag":"request-timeout","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}