Packages
nous
0.15.0
0.17.0
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.17
0.12.16
0.12.15
0.12.14
0.12.13
0.12.12
0.12.11
0.12.9
0.12.7
0.12.6
0.12.5
0.12.3
0.12.2
0.12.0
0.11.3
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.5.0
AI agent framework for Elixir with multi-provider LLM support
Current section
Files
Jump to
Current section
Files
lib/nous/errors.ex
defmodule Nous.Errors do
@moduledoc """
Custom error types for Nous AI.
These exceptions provide structured error information for different
failure scenarios in agent execution.
"""
defmodule ConfigurationError do
@moduledoc """
Error in configuration or missing dependencies.
Raised when required configuration is missing or a required
optional dependency is not available.
"""
defexception [:message, :details]
@type t :: %__MODULE__{
message: String.t(),
details: any()
}
@impl true
def exception(opts) when is_list(opts) do
message = Keyword.get(opts, :message, "Configuration error")
details = Keyword.get(opts, :details)
%__MODULE__{
message: message,
details: details
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
defmodule ModelError do
@moduledoc """
Error from the model provider API.
Raised when the underlying model API returns an error.
Note: Consider using `ProviderError` for new code.
"""
defexception [:message, :provider, :status_code, :details]
@type t :: %__MODULE__{
message: String.t(),
provider: atom() | nil,
status_code: integer() | nil,
details: any()
}
@impl true
def exception(opts) when is_list(opts) do
provider = Keyword.get(opts, :provider)
status_code = Keyword.get(opts, :status_code)
details = Keyword.get(opts, :details)
message =
opts[:message] ||
"Model request failed" <>
if(provider, do: " (#{provider})", else: "") <>
if(status_code, do: " [#{status_code}]", else: "")
%__MODULE__{
message: message,
provider: provider,
status_code: status_code,
details: details
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
defmodule ProviderError do
@moduledoc """
Error from an LLM provider.
Raised when a provider API call fails.
"""
defexception [:message, :provider, :status_code, :details]
@type t :: %__MODULE__{
message: String.t(),
provider: atom() | nil,
status_code: integer() | nil,
details: any()
}
@impl true
def exception(opts) when is_list(opts) do
provider = Keyword.get(opts, :provider)
status_code = Keyword.get(opts, :status_code)
details = Keyword.get(opts, :details)
message =
opts[:message] ||
"Provider request failed" <>
if(provider, do: " (#{provider})", else: "") <>
if(status_code, do: " [#{status_code}]", else: "")
%__MODULE__{
message: message,
provider: provider,
status_code: status_code,
details: details
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
defmodule ToolError do
@moduledoc """
Error during tool execution.
Raised when a tool function fails during execution.
"""
defexception [:message, :tool_name, :attempt, :original_error]
@type t :: %__MODULE__{
message: String.t(),
tool_name: String.t() | nil,
attempt: non_neg_integer() | nil,
original_error: any()
}
@impl true
def exception(opts) when is_list(opts) do
tool_name = Keyword.get(opts, :tool_name)
attempt = Keyword.get(opts, :attempt)
original_error = Keyword.get(opts, :original_error)
message =
opts[:message] ||
"Tool execution failed" <>
if(tool_name, do: " (#{tool_name})", else: "") <>
if(attempt, do: " after #{attempt} attempt(s)", else: "")
%__MODULE__{
message: message,
tool_name: tool_name,
attempt: attempt,
original_error: original_error
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
defmodule ToolTimeout do
@moduledoc """
Error when a tool execution times out.
Raised when a tool takes longer than its configured timeout.
"""
defexception [:message, :tool_name, :timeout]
@type t :: %__MODULE__{
message: String.t(),
tool_name: String.t() | nil,
timeout: non_neg_integer() | nil
}
@impl true
def exception(opts) when is_list(opts) do
tool_name = Keyword.get(opts, :tool_name)
timeout = Keyword.get(opts, :timeout)
message =
opts[:message] ||
"Tool '#{tool_name || "unknown"}' timed out after #{timeout || 0}ms"
%__MODULE__{
message: message,
tool_name: tool_name,
timeout: timeout
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
defmodule ValidationError do
@moduledoc """
Error during output validation.
Raised when structured output fails Ecto validation.
"""
defexception [:message, :errors, :output_type]
@type t :: %__MODULE__{
message: String.t(),
errors: keyword() | nil,
output_type: module() | nil
}
@impl true
def exception(opts) when is_list(opts) do
errors = Keyword.get(opts, :errors)
output_type = Keyword.get(opts, :output_type)
message =
opts[:message] ||
"Output validation failed" <>
if(output_type, do: " for #{inspect(output_type)}", else: "")
%__MODULE__{
message: message,
errors: errors,
output_type: output_type
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
defmodule UsageLimitExceeded do
@moduledoc """
Error when usage limits are exceeded.
Raised when an agent run exceeds configured limits for
requests, tokens, or tool calls.
"""
defexception [:message, :limit_type, :limit_value, :actual_value]
@type t :: %__MODULE__{
message: String.t(),
limit_type: atom() | nil,
limit_value: integer() | nil,
actual_value: integer() | nil
}
@impl true
def exception(opts) when is_list(opts) do
limit_type = Keyword.get(opts, :limit_type)
limit_value = Keyword.get(opts, :limit_value)
actual_value = Keyword.get(opts, :actual_value)
message =
opts[:message] ||
"Usage limit exceeded" <>
if(limit_type, do: " (#{limit_type})", else: "") <>
if(limit_value && actual_value,
do: ": #{actual_value} > #{limit_value}",
else: ""
)
%__MODULE__{
message: message,
limit_type: limit_type,
limit_value: limit_value,
actual_value: actual_value
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
defmodule MaxIterationsExceeded do
@moduledoc """
Error when agent loop exceeds maximum iterations.
Raised when an agent makes too many back-and-forth calls
with the model, possibly indicating an infinite loop.
"""
defexception [:message, :max_iterations]
@type t :: %__MODULE__{
message: String.t(),
max_iterations: pos_integer() | nil
}
@impl true
def exception(opts) when is_list(opts) do
max_iterations = Keyword.get(opts, :max_iterations)
message =
opts[:message] ||
"Maximum iterations exceeded" <>
if(max_iterations, do: " (#{max_iterations})", else: "")
%__MODULE__{
message: message,
max_iterations: max_iterations
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
defmodule ExecutionCancelled do
@moduledoc """
Error when agent execution is cancelled.
Raised when an agent execution is explicitly cancelled
by the user or system.
"""
defexception [:message, :reason]
@type t :: %__MODULE__{
message: String.t(),
reason: String.t() | nil
}
@impl true
def exception(opts) when is_list(opts) do
reason = Keyword.get(opts, :reason)
message =
opts[:message] ||
"Execution cancelled" <>
if(reason, do: ": #{reason}", else: "")
%__MODULE__{
message: message,
reason: reason
}
end
def exception(message) when is_binary(message) do
%__MODULE__{message: message}
end
end
end