use thiserror::Error;
#[derive(Error, Debug)]
pub enum StrandsError {
#[error("Model error: {message}")]
ModelError {
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync>>,
},
#[error("Model throttled: {message}")]
ModelThrottled { message: String },
#[error("Tool execution error in '{tool_name}': {message}")]
ToolError { tool_name: String, message: String },
#[error("Tool not found: {tool_name}")]
ToolNotFound { tool_name: String },
#[error("Tool validation error: {message}")]
ToolValidationError { message: String },
#[error("Invalid tool name '{name}': {reason}")]
InvalidToolName { name: String, reason: String },
#[error("Duplicate tool name: {name}")]
DuplicateToolName { name: String },
#[error("Invalid tool use: '{name}' not found. Available tools: {available_tools:?}")]
InvalidToolUseName { name: String, available_tools: Vec<String> },
#[error("Context window overflow: {message}")]
ContextWindowOverflow { message: String },
#[error("Max tokens reached")]
MaxTokensReached,
#[error("Content filtered: {message}")]
ContentFiltered { message: String },
#[error("Guardrail intervention: {message}")]
GuardrailIntervention { message: String },
#[error("Event loop error: {message}")]
EventLoopError { message: String },
#[error("Session error: {message}")]
SessionError { message: String },
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
#[error("Configuration error: {message}")]
ConfigurationError { message: String },
#[error("Invalid input: {message}")]
InvalidInput { message: String },
#[error("Internal error: {message}")]
InternalError { message: String },
#[error("Structured output error: {message}")]
StructuredOutputError { message: String },
#[error("Agent interrupted: {message}")]
Interrupted { message: String },
#[error("Multi-agent error: {message}")]
MultiAgentError { message: String },
#[error("Network error: {0}")]
NetworkError(String),
#[error("AWS error: {0}")]
AwsError(String),
#[error("MCP client initialization error: {message}")]
MCPClientInitializationError { message: String },
#[error("Tool provider error: {message}")]
ToolProviderError { message: String },
#[error("Not implemented: {feature}")]
NotImplemented { feature: String },
}
impl StrandsError {
pub fn model_error(message: impl Into<String>) -> Self {
Self::ModelError { message: message.into(), source: None }
}
pub fn model_error_with_source(
message: impl Into<String>,
source: impl std::error::Error + Send + Sync + 'static,
) -> Self {
Self::ModelError { message: message.into(), source: Some(Box::new(source)) }
}
pub fn tool_error(tool_name: impl Into<String>, message: impl Into<String>) -> Self {
Self::ToolError { tool_name: tool_name.into(), message: message.into() }
}
pub fn config_error(message: impl Into<String>) -> Self {
Self::ConfigurationError { message: message.into() }
}
pub fn invalid_input(message: impl Into<String>) -> Self {
Self::InvalidInput { message: message.into() }
}
pub fn is_retryable(&self) -> bool {
matches!(self, Self::ModelThrottled { .. } | Self::NetworkError(_))
}
}
pub type Result<T> = std::result::Result<T, StrandsError>;