BamlAbortError

Overview

BamlAbortError is thrown when a BAML function call is cancelled via an abort controller. This error indicates that the operation was intentionally stopped rather than failing due to an actual error condition.

Class Definition

1export class BamlAbortError extends Error {
2 public readonly name: string = 'BamlAbortError'
3 public readonly reason?: any
4
5 constructor(message: string, reason?: any) {
6 super(message)
7 this.reason = reason
8 }
9}

Properties

message

Type: string

Description of why the operation was aborted. This is typically a generic message like “Operation aborted” unless a specific message was provided during cancellation.

reason

Type: any (TypeScript/Python) / interface{} (Go) / Object (Ruby)

Optional additional context about the cancellation. This can be any value provided when calling the abort() method.

name

Type: string

Always returns "BamlAbortError" for easy error type identification.

Error Detection

TypeScript

1import { BamlAbortError } from '@/baml_client'
2
3try {
4 const result = await b.FunctionName(input, {
5 abortController: controller
6 })
7} catch (error) {
8 // Method 1: instanceof check (recommended)
9 if (error instanceof BamlAbortError) {
10 console.log('Operation was cancelled')
11 }
12
13 // Method 2: name check (works with minification)
14 if (error.name === 'BamlAbortError') {
15 console.log('Operation was cancelled')
16 }
17}

Python

1from baml_py import BamlAbortError
2
3try:
4 result = await b.FunctionName(
5 input,
6 baml_options={"abort_controller": controller}
7 )
8except BamlAbortError as e:
9 print(f"Operation was cancelled: {e}")
10 if e.reason:
11 print(f"Reason: {e.reason}")
12except Exception as e:
13 # Handle other errors
14 raise

Go

1import (
2 "context"
3 "errors"
4)
5
6result, err := b.FunctionName(ctx, input)
7if err != nil {
8 if errors.Is(err, context.Canceled) {
9 // Direct cancellation
10 fmt.Println("Operation was cancelled")
11 } else if errors.Is(err, context.DeadlineExceeded) {
12 // Timeout-based cancellation
13 fmt.Println("Operation timed out")
14 } else {
15 // Other error
16 return err
17 }
18}

Ruby

1begin
2 result = b.function_name(
3 input,
4 baml_options: { abort_controller: controller }
5 )
6rescue Baml::AbortError => e
7 puts "Operation was cancelled: #{e.message}"
8 puts "Reason: #{e.reason}" if e.reason
9rescue => e
10 # Handle other errors
11 raise
12end

Common Patterns

Distinguishing Cancellation Types

1try {
2 const result = await b.FunctionName(input, {
3 abortController: controller
4 })
5} catch (error) {
6 if (error instanceof BamlAbortError) {
7 if (error.reason === 'user_cancelled') {
8 // User explicitly cancelled
9 showMessage('You cancelled the operation')
10 } else if (error.reason === 'timeout') {
11 // Timeout occurred
12 showMessage('Operation timed out. Please try again.')
13 } else {
14 // Generic cancellation
15 showMessage('Operation was cancelled')
16 }
17 } else {
18 // Handle other errors
19 throw error
20 }
21}

Cleanup After Cancellation

1const controller = new AbortController()
2let cleanup = null
3
4try {
5 // Set up resources
6 cleanup = await setupResources()
7
8 const result = await b.FunctionName(input, {
9 abortController: controller
10 })
11
12 return result
13} catch (error) {
14 if (error instanceof BamlAbortError) {
15 console.log('Operation cancelled, cleaning up...')
16 }
17 throw error
18} finally {
19 // Always cleanup, whether cancelled or not
20 if (cleanup) {
21 await cleanup()
22 }
23}

Retry Logic with Abort Errors

1async function retryableOperation(input: any, maxRetries: number = 3) {
2 for (let attempt = 1; attempt <= maxRetries; attempt++) {
3 const controller = new AbortController()
4
5 try {
6 // Set timeout for each attempt
7 setTimeout(() => controller.abort('timeout'), 30000)
8
9 return await b.FunctionName(input, {
10 abortController: controller
11 })
12 } catch (error) {
13 if (error instanceof BamlAbortError) {
14 if (error.reason === 'timeout' && attempt < maxRetries) {
15 console.log(`Attempt ${attempt} timed out, retrying...`)
16 continue
17 }
18 // Don't retry for user cancellations
19 throw error
20 }
21 // Don't retry for other errors
22 throw error
23 }
24 }
25}

Integration with Streaming

When streaming operations are cancelled, the error behavior differs slightly:

1const controller = new AbortController()
2const stream = b.stream.FunctionName(input, {
3 abortController: controller
4})
5
6try {
7 for await (const chunk of stream) {
8 // Process chunk
9 if (shouldCancel) {
10 controller.abort('user_request')
11 }
12 }
13} catch (error) {
14 if (error instanceof BamlAbortError) {
15 // Stream was cancelled
16 console.log('Stream cancelled:', error.reason)
17 }
18}

Best Practices

1. Always Handle Abort Errors Explicitly

1// Good: Explicit handling
2try {
3 await operation()
4} catch (error) {
5 if (error instanceof BamlAbortError) {
6 // Handle cancellation specifically
7 return { cancelled: true }
8 }
9 // Re-throw unexpected errors
10 throw error
11}
12
13// Bad: Generic error handling
14try {
15 await operation()
16} catch (error) {
17 // All errors treated the same
18 console.error('Failed:', error)
19}

2. Provide Meaningful Cancellation Reasons

1// Good: Clear reason
2controller.abort('user_clicked_cancel')
3controller.abort({ type: 'timeout', duration: 30000 })
4
5// Bad: No reason
6controller.abort()

3. Don’t Retry Cancelled Operations

1// Good: Check error type before retry
2if (error instanceof BamlAbortError) {
3 // Don't retry - it was intentionally cancelled
4 return
5}
6
7// Bad: Retry everything
8for (let i = 0; i < 3; i++) {
9 try {
10 return await operation()
11 } catch (error) {
12 // This might retry a cancelled operation!
13 continue
14 }
15}