Skip to content

Add structured error handling with exception hierarchy - #7

Merged
jdoss merged 2 commits into
masterfrom
error-handling-cleanup
Apr 6, 2026
Merged

Add structured error handling with exception hierarchy#7
jdoss merged 2 commits into
masterfrom
error-handling-cleanup

Conversation

@jdoss

@jdoss jdoss commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add psi/errors.py with PsiError, ConfigError, ProviderError, and SecretNotFoundError
  • Top-level handler in cli.py main(): user errors exit 1 with message, bugs exit 2 with traceback
  • Catch ValidationError in load_settings(), translate to ConfigError with per-field details
  • Replace RuntimeError/ValueError with ProviderError in both providers, PKCS#11, and PIN resolution
  • Structured JSON error bodies ({"error": "...", "detail": "..."}) from the HTTP serve handler
  • Shell driver lookup() catches PsiError and routes through _fail() for plain-text stderr output

Test plan

  • ruff check and ruff format --check pass
  • ty check passes
  • All 187 tests pass (24 new tests for error handling)
  • Manual: psi setup with missing config shows friendly error, no traceback
  • Manual: psi setup with invalid YAML shows friendly error

jdoss added 2 commits April 1, 2026 23:19
Replace raw Python stack traces with user-friendly error messages for
all user-facing errors (bad config, provider failures, missing secrets).

- Add psi/errors.py with PsiError, ConfigError, ProviderError, and
  SecretNotFoundError exception classes
- Add top-level exception handler in cli.py main() that catches known
  errors (exit 1) and wraps unexpected errors as bug reports (exit 2)
- Catch ValidationError in settings.py load_settings() and translate
  to ConfigError with per-field details
- Replace RuntimeError/ValueError with ProviderError in both providers,
  PKCS#11 session management, and PIN resolution
- Return structured JSON error bodies from the HTTP serve handler
- Catch PsiError in shell driver lookup() and route through _fail()
- Catch yaml.YAMLError in load_settings() and raise ConfigError
- Catch httpx.ConnectError in Infisical provider lookup() and setup.py
  for unreachable API errors
@jdoss
jdoss merged commit b19b96e into master Apr 6, 2026
2 checks passed
@jdoss
jdoss deleted the error-handling-cleanup branch April 6, 2026 10:53
jdoss added a commit that referenced this pull request Apr 8, 2026
The error-handling cleanup in #7 wrapped lookup-path httpx errors but
missed psi/providers/infisical/auth.py:_parse_token_response. When
Infisical returned 502 during its own boot, the raw HTTPStatusError
escaped through psi setup's retry loop and surfaced as the CLI
bug-report panel instead of a clean error message.

Wrap the auth response in ProviderError with the status code and a body
snippet, preserving __cause__ so setup._is_retryable still unwraps and
retries 502/503/404. Add httpx.HTTPError as a last-resort catch in
cli.main() so any future stray httpx exception lands as "Network error"
instead of the bug panel.

Tests: unit coverage for _parse_token_response wrapping; setup retry
tests covering a 502 wrapped as ProviderError retrying through all
attempts and a 401 wrapped as ProviderError failing immediately; CLI
tests for the httpx fallback branch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant