Catalog PyPI
Back to packageRELEASE DETAILS

0.2.0

PyPI

actionable-errors

Three-audience error framework: typed errors for code, actionable suggestions for humans, tool guidance for AI agents

Published9 Mar 2026
Direct dependencies7
Transitive dependenciesNot calculated

README

Version 0.2.0 documentation

actionable-errors

CI Coverage PyPI

Three-audience error framework for Python.

Every ActionableError speaks to three audiences simultaneously:

AudienceUsesProvided by
Calling codeTyped ErrorType for routing (retry? escalate? ignore?)ErrorType(StrEnum) — 8 base categories
Human operatorsuggestion + Troubleshooting stepsFrozen dataclasses with actionable text
AI agentAIGuidance with concrete next tool callsFrozen dataclass with tool suggestions

Install

pip install actionable-errors

Zero runtime dependencies — stdlib only. Sits at the bottom of every dependency tree.

Quick Start

from actionable_errors import (
    ActionableError,
    AIGuidance,
    ToolResult,
    from_exception,
    sanitize,
)

# Domain-specific factory with built-in defaults
error = ActionableError.authentication(
    service="Azure DevOps",
    raw_error="401 Unauthorized",
)
print(error.suggestion)    # "Check your credentials and try again."
print(error.ai_guidance)   # AIGuidance(action_required="Re-authenticate", command="az login")

# Auto-classify any exception
try:
    raise ConnectionError("Connection refused")
except Exception as exc:
    ae = from_exception(exc, service="Kusto", operation="query")
    print(ae.error_type)   # "connection"

# Typed result envelope for MCP tool responses
result = ToolResult.ok(data={"items": 42})
result = ToolResult.fail(error=error)     # extracts error_type + suggestion

# Credential sanitization
clean = sanitize('password="hunter2" token=abc123')
# → 'password="***" token=***'

Extending ErrorType

Python StrEnum can't be subclassed once it has members, so extend via composition:

from enum import StrEnum
from actionable_errors import ActionableError

class RAGErrorType(StrEnum):
    EMBEDDING = "embedding"
    INDEX = "index"

error = ActionableError(
    error="Vector store unavailable",
    error_type=RAGErrorType.INDEX,
    service="pinecone",
    suggestion="Check Pinecone cluster status.",
)

Factories

Eight domain-specific factories with sensible defaults:

FactoryKey Parameters
.authentication(service, raw_error)Default suggestion + AI guidance
.configuration(field_name, reason)—
.connection(service, url, raw_error)—
.timeout(service, operation, timeout_seconds)—
.permission(service, resource, raw_error)—
.validation(service, field_name, reason)—
.not_found(service, resource_type, resource_id, raw_error)—
.internal(service, operation, raw_error)—

All factories accept optional suggestion, ai_guidance, and troubleshooting kwargs.

Development

# Install dev dependencies
uv sync --extra dev

# Run all checks
task check  # lint → type → test (90 tests, 100% coverage)

License

MIT

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 7

Native requirements
7 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
pre-commit
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pre-commit<5,>=4; extra == "dev"runtime
pyright
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pyright<2,>=1.1; extra == "dev"runtime
pytest-asyncio
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest-asyncio<1,>=0.24; extra == "dev"runtime
pytest-cov
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest-cov<7,>=6; extra == "dev"runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest<9,>=8; extra == "dev"runtime
ruff
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
ruff<1,>=0.8; extra == "dev"runtime
taskipy
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
taskipy<2,>=1.14; extra == "dev"runtime

Distribution files

2 collected
actionable_errors-0.2.0-py3-none-any.whl

bdist_wheel · 10.29 KB · Python py3

Source file
actionable_errors-0.2.0.tar.gz

sdist · 82.43 KB · Python source

Source file

Repository

PENDING
grimlor/actionable-errors

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 18:32 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:7fa24be34ffd38013bfd7b0477d416a33debd77dbf2ac1388945fc282ba6c377

Other collected versions

View all collected versions →