Error Handling & Exceptions
April 3, 2026 ยท View on GitHub
Import: from selectools.exceptions import SelectoolsError
Stability: stable
from selectools import Agent, SelectoolsError, tool
from selectools.providers.stubs import LocalProvider
@tool(description="Divide two numbers")
def divide(a: float, b: float) -> str:
if b == 0:
raise ValueError("Cannot divide by zero")
return str(a / b)
agent = Agent(tools=[divide], provider=LocalProvider())
try:
result = agent.run("Divide 10 by 0")
except SelectoolsError as e:
print(f"Caught: {e}")
!!! tip "See Also"
- Agent Module -- the agent loop that raises and handles these errors
- Tools Module -- ToolValidationError and ToolExecutionError details
All selectools exceptions inherit from SelectoolsError, so you can catch everything with a single handler or be specific.
Exception Hierarchy
graph TD
A["SelectoolsError<br/>Base catch-all"] --> B["ToolValidationError"]
A --> C["ToolExecutionError"]
A --> D["ProviderConfigurationError"]
A --> E["MemoryLimitExceededError"]
A --> F["GraphExecutionError"]
All exceptions include PyTorch-style error messages with clear explanations and fix suggestions.
Catching Errors
Catch Everything
from selectools import SelectoolsError
try:
result = agent.ask("Do something")
except SelectoolsError as e:
print(f"Selectools error: {e}")
Specific Handlers
from selectools import (
SelectoolsError,
ToolValidationError,
ToolExecutionError,
ProviderConfigurationError,
MemoryLimitExceededError,
GraphExecutionError,
)
try:
result = agent.ask("Process this data")
except ToolValidationError as e:
print(f"Bad params for tool '{e.tool_name}': {e.issue}")
print(f"Param: {e.param_name}")
if e.suggestion:
print(f"Fix: {e.suggestion}")
except ToolExecutionError as e:
print(f"Tool '{e.tool_name}' crashed: {e.error}")
print(f"Was called with: {e.params}")
except ProviderConfigurationError as e:
print(f"Provider '{e.provider_name}' misconfigured: {e.missing_config}")
if e.env_var:
print(f"Set: export {e.env_var}='your-key'")
except MemoryLimitExceededError as e:
print(f"Memory {e.limit_type} limit hit: {e.current}/{e.limit}")
except SelectoolsError as e:
print(f"Other selectools error: {e}")
ToolValidationError
When: The LLM provides parameters that don't match the tool's schema (wrong type, missing required field).
Attributes:
| Attribute | Type | Description |
|---|---|---|
tool_name | str | Name of the tool |
param_name | str | Which parameter failed |
issue | str | What went wrong |
suggestion | str | How to fix it |
Example output:
============================================================
โ Tool Validation Error: 'search'
============================================================
Parameter: limit
Issue: Expected int, got str
๐ก Suggestion: Pass an integer value for 'limit'
============================================================
ToolExecutionError
When: The tool function itself raises an exception during execution.
Attributes:
| Attribute | Type | Description |
|---|---|---|
tool_name | str | Name of the tool |
error | Exception | The original exception |
params | Dict[str, Any] | Parameters the tool was called with |
Example output:
============================================================
โ Tool Execution Failed: 'fetch_data'
============================================================
Error: ConnectionError: Could not reach api.example.com
Parameters: {'url': 'https://api.example.com/data'}
๐ก Check that:
- All required parameters are provided
- Parameter types match the tool's schema
- The tool function is correctly implemented
============================================================
ProviderConfigurationError
When: A provider is created without the required API key or configuration.
Attributes:
| Attribute | Type | Description |
|---|---|---|
provider_name | str | Provider name (e.g. "OpenAI") |
missing_config | str | What's missing |
env_var | str | Environment variable to set |
Example output:
============================================================
โ Provider Configuration Error: 'OpenAI'
============================================================
Missing: API key
๐ก How to fix:
1. Set the environment variable:
export OPENAI_API_KEY='your-api-key'
2. Or pass it directly:
provider = OpenAIProvider(api_key='your-api-key')
============================================================
MemoryLimitExceededError
When: Conversation memory exceeds its configured limit. In practice, the sliding window trims automatically, so this is only raised if there's an explicit constraint violation.
Attributes:
| Attribute | Type | Description |
|---|---|---|
current | int | Current count |
limit | int | Configured limit |
limit_type | str | "messages" or "tokens" |
Example output:
============================================================
โ ๏ธ Memory Limit Exceeded
============================================================
Limit Type: messages
Current: 40
Limit: 20
๐ก Suggestions:
- Increase max_messages: ConversationMemory(max_messages=40)
- Clear older messages manually: memory.clear()
============================================================
GraphExecutionError
When: A node in a multi-agent graph fails during execution. Pre-work for v0.17.0 multi-agent orchestration.
Attributes:
| Attribute | Type | Description |
|---|---|---|
graph_name | str | Name of the graph |
node_name | str | Node that failed |
error | Exception | The original exception |
step | int | Step number in the graph |
Example output:
============================================================
โ Graph Execution Failed: 'research-pipeline'
============================================================
Node: summarize (step 3)
Error: ProviderError: Rate limit exceeded
๐ก Check that:
- The node 'summarize' is correctly configured
- All required inputs are available at step 3
- The node's agent or function is working correctly
============================================================
Other Errors
These are not selectools-specific but you may encounter them:
| Error | When |
|---|---|
GuardrailError | A guardrail with action=block rejected content (see GUARDRAILS.md) |
ProviderError | An LLM API request failed (raised by providers, caught/retried by agent) |
ValueError | Invalid configuration (e.g. get_tools_by_category("invalid")) |
from selectools.guardrails import GuardrailError
from selectools.providers.base import ProviderError
try:
result = agent.ask("...")
except GuardrailError as e:
print(f"Content blocked by {e.guardrail_name}: {e.reason}")
except ProviderError:
print("LLM provider failed after all retries")
Related Examples
| # | File | Description |
|---|---|---|
| 29 | 29_guardrails.py | Guardrail error handling patterns |
| 25 | 25_provider_fallback.py | Provider error recovery with fallbacks |
Best Practice: Production Error Handling
from selectools import Agent, SelectoolsError
from selectools.guardrails import GuardrailError
from selectools.providers.base import ProviderError
def safe_ask(agent: Agent, prompt: str) -> str:
try:
result = agent.ask(prompt)
return result.content
except GuardrailError as e:
return f"Your request was blocked: {e.reason}"
except ProviderError:
return "The AI service is temporarily unavailable. Please try again."
except SelectoolsError as e:
log.error(f"Agent error: {e}")
return "Something went wrong processing your request."