Back to Baml

BamlAbortError

fern/03-reference/baml_client/errors/baml-abort-error.mdx

0.222.09.4 KB
Original Source

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

<Tabs> <Tab title="TypeScript" language="typescript"> ```typescript export class BamlAbortError extends Error { public readonly name: string = 'BamlAbortError' public readonly reason?: any public readonly detailed_message: string
  constructor(message: string, reason?: any, detailed_message: string = '') {
    super(message)
    this.reason = reason
    this.detailed_message = detailed_message
  }
}
```
</Tab> <Tab title="Python" language="python"> ```python class BamlAbortError(Exception): """Error raised when a BAML operation is aborted"""
    def __init__(self, message: str, reason: Any = None, detailed_message: str = ''):
        super().__init__(message)
        self.reason = reason
        self.detailed_message = detailed_message
        self.name = 'BamlAbortError'
```
</Tab> <Tab title="Go" language="go"> ```go // In Go, cancellation is handled via context errors import ( "context" "errors" )
// Check for cancellation
if errors.Is(err, context.Canceled) {
    // Operation was cancelled
}
if errors.Is(err, context.DeadlineExceeded) {
    // Operation timed out
}
```
</Tab> <Tab title="Rust" language="rust"> ```rust // In Rust, cancellation errors are returned as Result::Err // Check the error message for cancellation/timeout indicators use baml::CancellationToken; use myproject::baml_client::sync_client::B;
let input = input(); // Your input data
let token = CancellationToken::new();
match B.FunctionName.with_cancellation_token(Some(token)).call(input) {
    Ok(result) => { /* success */ }
    Err(e) => {
        let err = format!("{:?}", e).to_lowercase();
        if err.contains("cancel") || err.contains("timeout") {
            // Operation was cancelled or timed out
        }
    }
}
```
</Tab> <Tab title="Ruby" language="ruby"> ```ruby module Baml class AbortError < StandardError attr_reader :reason, :detailed_message
    def initialize(message, reason = nil, detailed_message = '')
      super(message)
      @reason = reason
      @detailed_message = detailed_message
    end
  end
end
```
</Tab> </Tabs>

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.

detailed_message

Type: string

Comprehensive error information that includes the complete history of all failed attempts when using fallback clients or retry policies. For abort errors, this typically contains the same information as message but may include additional debugging details about the cancellation context.

Error Detection

TypeScript

typescript
import { BamlAbortError } from '@/baml_client'

try {
  const result = await b.FunctionName(input, {
    abortController: controller
  })
} catch (error) {
  // Method 1: instanceof check (recommended)
  if (error instanceof BamlAbortError) {
    console.log('Operation was cancelled')
  }
  
  // Method 2: name check (works with minification)
  if (error.name === 'BamlAbortError') {
    console.log('Operation was cancelled')
  }
}

Python

python
from baml_py import BamlAbortError

try:
    result = await b.FunctionName(
        input,
        baml_options={"abort_controller": controller}
    )
except BamlAbortError as e:
    print(f"Operation was cancelled: {e}")
    if e.reason:
        print(f"Reason: {e.reason}")
except Exception as e:
    # Handle other errors
    raise

Go

go
import (
    "context"
    "errors"
)

result, err := b.FunctionName(ctx, input)
if err != nil {
    if errors.Is(err, context.Canceled) {
        // Direct cancellation
        fmt.Println("Operation was cancelled")
    } else if errors.Is(err, context.DeadlineExceeded) {
        // Timeout-based cancellation
        fmt.Println("Operation timed out")
    } else {
        // Other error
        return err
    }
}

Ruby

ruby
begin
  result = b.function_name(
    input,
    baml_options: { abort_controller: controller }
  )
rescue Baml::AbortError => e
  puts "Operation was cancelled: #{e.message}"
  puts "Reason: #{e.reason}" if e.reason
rescue => e
  # Handle other errors
  raise
end

Common Patterns

Distinguishing Cancellation Types

typescript
try {
  const result = await b.FunctionName(input, {
    abortController: controller
  })
} catch (error) {
  if (error instanceof BamlAbortError) {
    if (error.reason === 'user_cancelled') {
      // User explicitly cancelled
      showMessage('You cancelled the operation')
    } else if (error.reason === 'timeout') {
      // Timeout occurred
      showMessage('Operation timed out. Please try again.')
    } else {
      // Generic cancellation
      showMessage('Operation was cancelled')
    }
  } else {
    // Handle other errors
    throw error
  }
}

Cleanup After Cancellation

typescript
const controller = new AbortController()
let cleanup = null

try {
  // Set up resources
  cleanup = await setupResources()
  
  const result = await b.FunctionName(input, {
    abortController: controller
  })
  
  return result
} catch (error) {
  if (error instanceof BamlAbortError) {
    console.log('Operation cancelled, cleaning up...')
  }
  throw error
} finally {
  // Always cleanup, whether cancelled or not
  if (cleanup) {
    await cleanup()
  }
}

Retry Logic with Abort Errors

typescript
async function retryableOperation(input: any, maxRetries: number = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    const controller = new AbortController()
    
    try {
      // Set timeout for each attempt
      setTimeout(() => controller.abort('timeout'), 30000)
      
      return await b.FunctionName(input, {
        abortController: controller
      })
    } catch (error) {
      if (error instanceof BamlAbortError) {
        if (error.reason === 'timeout' && attempt < maxRetries) {
          console.log(`Attempt ${attempt} timed out, retrying...`)
          continue
        }
        // Don't retry for user cancellations
        throw error
      }
      // Don't retry for other errors
      throw error
    }
  }
}

Integration with Streaming

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

<Tabs> <Tab title="TypeScript" language="typescript"> ```typescript const controller = new AbortController() const stream = b.stream.FunctionName(input, { abortController: controller })
try {
  for await (const chunk of stream) {
    // Process chunk
    if (shouldCancel) {
      controller.abort('user_request')
    }
  }
} catch (error) {
  if (error instanceof BamlAbortError) {
    // Stream was cancelled
    console.log('Stream cancelled:', error.reason)
  }
}
```
</Tab> <Tab title="Python" language="python"> ```python controller = AbortController() stream = b.stream.FunctionName( input, baml_options={"abort_controller": controller} )
try:
    async for chunk in stream:
        # Process chunk
        if should_cancel:
            controller.abort('user_request')
except BamlAbortError as e:
    # Stream was cancelled
    print(f"Stream cancelled: {e.reason}")
```
</Tab> </Tabs>

Best Practices

1. Always Handle Abort Errors Explicitly

typescript
// Good: Explicit handling
try {
  await operation()
} catch (error) {
  if (error instanceof BamlAbortError) {
    // Handle cancellation specifically
    return { cancelled: true }
  }
  // Re-throw unexpected errors
  throw error
}

// Bad: Generic error handling
try {
  await operation()
} catch (error) {
  // All errors treated the same
  console.error('Failed:', error)
}

2. Provide Meaningful Cancellation Reasons

typescript
// Good: Clear reason
controller.abort('user_clicked_cancel')
controller.abort({ type: 'timeout', duration: 30000 })

// Bad: No reason
controller.abort()

3. Don't Retry Cancelled Operations

typescript
// Good: Check error type before retry
if (error instanceof BamlAbortError) {
  // Don't retry - it was intentionally cancelled
  return
}

// Bad: Retry everything
for (let i = 0; i < 3; i++) {
  try {
    return await operation()
  } catch (error) {
    // This might retry a cancelled operation!
    continue
  }
}