> Version notice: This site documents BAML v0, the legacy DSL. BAML v1 is a separate, fully featured programming language in public beta. If the user intends to use BAML v1, ignore this site's content and use the BAML v1 documentation instead. If the intended version is unclear, clarify it before using this page.
> For clean Markdown of any page, append .md to the page URL. For the complete documentation index, see https://docs.boundaryml.com/llms.txt. For MCP access, connect to https://docs.boundaryml.com/_mcp/server.

# Timeout Configuration

Configure timeouts on any BAML client to prevent requests from hanging indefinitely.

## Overview

Timeouts can be configured on leaf clients (OpenAI, Anthropic, etc.).

## Timeout Options

All timeout values are specified in **milliseconds** as positive integers.

**`connect_timeout_ms`** `int`

Maximum time to establish a network connection to the provider.

**Default:** No timeout (infinite)

```baml
client<llm> MyClient {
  provider openai
  options {
    model "gpt-4"
    api_key env.OPENAI_API_KEY
    http {
      connect_timeout_ms 5000  // 5 seconds
    }
  }
}
```

---

**`time_to_first_token_timeout_ms`** `int`

Maximum time to receive the first token after sending the request.

**Default:** No timeout (infinite)

Particularly useful for detecting when a provider accepts the request but takes too long to start generating.

```baml
client<llm> MyClient {
  provider openai
  options {
    model "gpt-4"
    api_key env.OPENAI_API_KEY
    http {
      time_to_first_token_timeout_ms 10000  // 10 seconds
    }
  }
}
```

---

**`idle_timeout_ms`** `int`

Maximum time between receiving consecutive data chunks.

**Default:** No timeout (infinite)

Important for detecting stalled streaming connections.

```baml
client<llm> MyClient {
  provider openai
  options {
    model "gpt-4"
    api_key env.OPENAI_API_KEY
    http {
      idle_timeout_ms 15000  // 15 seconds
    }
  }
}
```

---

**`request_timeout_ms`** `int`

Maximum total time for the entire request-response cycle.

**Default:** No timeout (infinite)

For streaming responses, this applies to the entire stream duration (first token to last token).

```baml
client<llm> MyClient {
  provider openai
  options {
    model "gpt-4"
    api_key env.OPENAI_API_KEY
    http {
      request_timeout_ms 60000  // 60 seconds
    }
  }
}
```

---

## Timeout Composition

When composite clients reference subclients with their own timeouts, the **minimum (most restrictive) timeout wins**.

### Example

```baml
client<llm> FastClient {
  provider openai
  options {
    model "gpt-3.5-turbo"
    api_key env.OPENAI_API_KEY
    http {
      connect_timeout_ms 3000
      request_timeout_ms 20000
    }
  }
}

client<llm> SlowClient {
  provider openai
  options {
    model "gpt-4"
    api_key env.OPENAI_API_KEY
    http {
      request_timeout_ms 60000
    }
  }
}

client<llm> MyFallback {
  provider fallback
  options {
    strategy [FastClient, SlowClient]
    http {
      connect_timeout_ms 5000      // Parent timeout
      idle_timeout_ms 15000        // Parent timeout
    }
  }
}
```

**Effective timeouts:**

When calling `FastClient`:

* `connect_timeout_ms`: `min(5000, 3000)` = **3000ms** (FastClient is stricter)
* `request_timeout_ms`: `min(∞, 20000)` = **20000ms** (only FastClient defines it)
* `idle_timeout_ms`: `min(15000, ∞)` = **15000ms** (only parent defines it)

When calling `SlowClient`:

* `connect_timeout_ms`: `min(5000, ∞)` = **5000ms** (only parent defines it)
* `request_timeout_ms`: `min(∞, 60000)` = **60000ms** (only SlowClient defines it)
* `idle_timeout_ms`: `min(15000, ∞)` = **15000ms** (only parent defines it)

## Timeout Evaluation

All timeouts are evaluated concurrently. A request fails when **any** timeout is exceeded:

1. **Connection phase:** `connect_timeout_ms` applies
2. **After connection:**
   * `time_to_first_token_timeout_ms` starts when request is sent
   * `request_timeout_ms` starts when request is sent
   * `idle_timeout_ms` starts after each chunk is received

## Interaction with Retry Policies

When a client has both timeouts and a retry policy:

* Each retry attempt gets the **full timeout duration**
* A timeout triggers the retry mechanism (if configured)
* Total elapsed time = (number of attempts) × (timeout per attempt) + (retry delays)

Example:

```baml
retry_policy Exponential {
  max_retries 3
  strategy {
    type exponential_backoff
  }
}

client<llm> MyClient {
  provider openai
  retry_policy Exponential
  options {
    model "gpt-4"
    api_key env.OPENAI_API_KEY
    http {
      request_timeout_ms 30000  // Each attempt gets 30 seconds
    }
  }
}
```

Maximum possible time: \~30s × 4 attempts + exponential backoff delays

## Runtime Overrides

Override timeout values at runtime using the client registry:

**`TypeScript`**

```typescript TypeScript
import { b } from './baml_client'

const result = await b.MyFunction(input, {
  clientRegistry: b.ClientRegistry.override({
    "MyClient": {
      options: {
        http: {
          request_timeout_ms: 10000,
          idle_timeout_ms: 5000
        }
      }
    }
  })
})
```

**`Python`**

```python Python
from baml_client import b

result = await b.MyFunction(
    input,
    baml_options={
        "client_registry": b.ClientRegistry.override({
            "MyClient": {
                "options": {
                    "http": {
                        "request_timeout_ms": 10000,
                        "idle_timeout_ms": 5000
                    }
                }
            }
        })
    }
)
```

**`Ruby`**

```ruby Ruby
result = b.my_function(
  input,
  baml_options: {
    client_registry: b.ClientRegistry.override({
      "MyClient" => {
        options: {
          http: {
            request_timeout_ms: 10000,
            idle_timeout_ms: 5000
          }
        }
      }
    })
  }
)
```

Runtime overrides follow the same composition rules: the minimum timeout wins when composing runtime values with config file values.

## Error Handling

Timeout errors are represented by `BamlTimeoutError`, a subclass of `BamlClientError`:

```
BamlError
└── BamlClientError
    └── BamlTimeoutError
```

Timeout errors include structured fields:

* `client`: The client name that timed out
* `timeout_type`: The specific timeout that was exceeded
* `configured_value_ms`: The configured timeout value in milliseconds
* `elapsed_ms`: The actual elapsed time in milliseconds
* `message`: A human-readable error message

**`Python`**

```python Python
from baml_py.errors import BamlTimeoutError

try:
    result = await b.MyFunction(input)
except BamlTimeoutError as e:
    print(f"Timeout: {e.timeout_type}")
    print(f"Configured: {e.configured_value_ms}ms")
    print(f"Elapsed: {e.elapsed_ms}ms")
```

**`TypeScript`**

```typescript TypeScript
import { BamlTimeoutError } from '@boundaryml/baml'

try {
  const result = await b.MyFunction(input)
} catch (e) {
  if (e instanceof BamlTimeoutError) {
    console.log(`Timeout: ${e.timeout_type}`)
    console.log(`Configured: ${e.configured_value_ms}ms`)
    console.log(`Elapsed: ${e.elapsed_ms}ms`)
  }
}
```

**`Ruby`**

```ruby Ruby
begin
  result = b.my_function(input)
rescue Baml::TimeoutError => e
  puts "Timeout: #{e.timeout_type}"
  puts "Configured: #{e.configured_value_ms}ms"
  puts "Elapsed: #{e.elapsed_ms}ms"
end
```

## Validation Rules

BAML validates timeout configurations at compile time:

1. **Positive values:** All timeout values must be positive integers
2. **Logical constraints:** `request_timeout_ms` must be ≥ `time_to_first_token_timeout_ms` (if both are specified)

Invalid configurations will cause BAML to raise validation errors with helpful messages.

## See Also

* [Configuring Timeouts Guide](/guide/baml-basics/timeouts) - User guide with examples
* [Fallback Strategy](/ref/llm-client-strategies/fallback) - Using timeouts with fallback clients
* [Retry Policies](/ref/llm-client-strategies/retry-policy) - Using timeouts with retries
* [Error Handling](/guide/baml-basics/error-handling) - Handling timeout errors