4.8 KiB
description, applyTo
| description | applyTo |
|---|---|
| Cross-cutting error handling rules for services, API, and UI. | src/transcription/**/*.py |
Error Handling (Cross-cutting)
Primary references:
docs/error_handling.mddocs/invariant/error_handling.mddocs/requirements.md
Taxonomy and Categories
Use category-driven semantics aligned to canonical policy:
validationnot_foundconflictexternaltimeoutinternal
Do not invent ad hoc categories in user/API-facing envelopes unless canonical docs are updated.
Runtime/internal categories may be more specific for diagnostics and persistence, but they must map
deterministically to the canonical envelope categories through the centralized mapper in
transcription.errors.canonical_error_category.
Current internal categories:
validation_erroruser_input_errornot_found_errorconflict_errorexternal_provider_errorexternal_timeout_errorprocessing_errorinfrastructure_transient_errorinfrastructure_persistent_errorinternal_unexpected_error
Required internal -> canonical mapping:
validation_error,user_input_error->validationnot_found_error->not_foundconflict_error->conflictexternal_provider_error->externalexternal_timeout_error,infrastructure_transient_error->timeoutprocessing_error,infrastructure_persistent_error,internal_unexpected_error->internal
Translation Boundaries
- Provider/adapters: raise provider/domain exceptions; do not emit UI text.
- Services: map raw exceptions into internal categories and preserve causal chain (
raise ... from ...). - UI/API: map internal category -> canonical envelope category and emit user-safe, actionable messages.
Retry Rules
- No auto-retry for
validation,not_found,conflict. external/timeoutmay be retried when operation semantics are safe.- Preserve each retry as new evidence where applicable (no history rewrite).
Job/Page Failure Semantics
- Page-level (
JobSource):pending,transcribed,failed,cancelled. - Job terminals:
transcribed,partial_success,failed. - Cancellation must keep job-level and page-level semantics explicit and consistent.
- Do not emit legacy terminal state language such as
completedin active user/API lifecycle contracts.
User-Safe Messaging
- Never leak stack traces, credentials, auth headers, or local filesystem paths in user-facing output.
- Include actionable remediation guidance aligned to category.
- Keep envelope structure consistent across API endpoints.
AppError.message vs AppError.detail
AppError carries two texts with different audiences, and they must not be collapsed. Getting this
wrong has already caused a real defect in this repository, in both directions.
| Attribute | Audience | Reaches | Rule |
|---|---|---|---|
message |
User and API clients | ErrorEnvelope.message, UI notifications |
Stays generic. Never embed exception text, provider payloads, or filesystem paths. |
detail |
Internal only | Logs, and format_error_detail -> ExecutionAttempt.error_detail and MaintenanceRun.error_detail |
Carries the root cause. Never rendered to users or serialized into an envelope. |
- Putting root-cause data in
messageleaks infrastructure detail to users. - Omitting it from
detailsilently degrades the provenance record this system exists to preserve — a failed attempt whoseerror_detailsays nothing is an attempt that cannot be diagnosed later. - When you raise from a caught exception, populate both: a generic
messageand adetailcarryingtype(exc).__name__and the exception text, withraise ... from exc. detailis optional (None). A read path that assumes it is populated must handle its absence.- Before changing either attribute, or any helper that formats them, enumerate every consumer — evidence writes, maintenance runs, logging, API envelopes, and UI presentation all read these fields, and tests assert on the persisted text.
Canonical definitions live in src/transcription/errors.py; see also docs/error_handling.md.
Logging and Diagnostics
- Log operation identifiers and error IDs where available.
- Preserve category + cause-chain context.
- Distinguish no-response timeout/network failures from returned provider error responses.
Guardrails
- No broad catch-and-swallow patterns.
- No success-shaped fallback values after exceptions.
- Category mapping must remain deterministic and testable.
Contract Sync Rule
If taxonomy, retries, or envelope semantics change:
- Update canonical docs (
docs/error_handling.md, and invariant docs if needed). - Update tests in the same change.
- Update related instruction/skill references.
- If change affects persisted status/category fields, update
docs/schema.mdwhen applicable.