aeat.core.errors._registry module

Structured error-code registry and CLI rendering helpers.

Centralises AEAT’s stable CLI error taxonomy. Every core.errors.AeatError subclass binds to a predeclared ErrorCode row through bind_error_code(), so the public contract stays explicit, reviewable, and grep-stable. Rendering helpers render_error_text() and render_error_json() produce the human-readable and machine-readable stderr payloads that downstream tools consume; build_error_envelope() constructs the underlying ErrorEnvelope.

Secret-looking context keys (matching _SECRET_FIELD_PATTERN) are redacted before they ever reach stderr — see scrub_error_context(). Non-secret context values are also passed through core.redaction.redact_for_log() so NIF, URL, and bearer-token shapes share the same rule vocabulary as logs and observability.

class ErrorCategory(*values)[source]

Bases: StrEnum

Closed catalogue of stable CLI error categories.

ERROR
REFUSED
AUTH
INTEGRITY
FAIL
INTERNAL
LOCKED
class ErrorCode(**data)[source]

Bases: BaseModel

Stable metadata attached to an core.errors.AeatError type.

Parameters:
code: str
category: ErrorCategory
message_key: str
default_suggestion: str | None
retryable: bool
runbook_id: str | None
class ErrorEnvelope(**data)[source]

Bases: BaseModel

Machine-readable error body nested under the shared envelope spine.

Rendered as the error member of the stderr error document. The document-level spine (schema_version, command, status, notices) is added by render_error_json() so the error document and the success core.json_contract.SchemaEnvelope share one outer shape.

Parameters:
  • code (str)

  • category (str)

  • message (str)

  • suggestion (str | None)

  • retryable (bool)

  • runbook_id (str | None)

  • context (dict[str, str] | None)

  • trace_id (str | None)

code: str
category: str
message: str
suggestion: str | None
retryable: bool
runbook_id: str | None
context: dict[str, str] | None
trace_id: str | None
register(code)[source]

Register code in the global catalogue.

Parameters:

code (ErrorCode) – The ErrorCode record to add.

Return type:

ErrorCode

Returns:

The same ErrorCode object for fluent use at declaration sites.

Raises:

ValueError – If a duplicate code identifier is encountered.

declared_error_codes()[source]

Return declared (qualified class name, :class:`ErrorCode`) registry rows.

Return type:

tuple[tuple[str, ErrorCode], ...]

bind_error_code(error_type)[source]

Bind a stable ErrorCode to error_type.

Called from AeatError.__init_subclass__ at class-creation time. If the global _DECLARED_CODE_BY_QUALNAME mapping is not yet available (the module is still initialising due to a circular import) the class is added to _DEFERRED_BIND and bound lazily on first use via get_registered_error_code().

Parameters:

error_type (type[BaseException]) – Error class being declared.

Return type:

ErrorCode | None

Returns:

The registered ErrorCode for error_type.

Raises:

ValueError – When the mapping is available but contains no entry for this class.

get_registered_error_code(error)[source]

Return the registered ErrorCode for error.

Drains any deferred binds accumulated during the circular-import window before attempting the lookup, so classes defined before _DECLARED_CODE_BY_QUALNAME was populated are bound here on first runtime use.

Return type:

ErrorCode

Parameters:

error (BaseException | type[BaseException])

resolve_output_language()[source]

Resolve the configured output language, defaulting to es.

Return type:

str

scrub_error_context(context)[source]

Redact secret-looking keys and strip internal keys from context.

Keys matching _SECRET_FIELD_PATTERN are replaced with "<redacted>". Keys in _INTERNAL_CONTEXT_KEYS are dropped entirely — they are implementation detail (e.g. widget prompt identifiers) and must not appear in operator-facing output.

Return type:

dict[str, str] | None

Parameters:

context (Mapping[str, object] | None)

build_error_envelope(error, *, context=None, trace_id=None)[source]

Build the deterministic JSON stderr envelope for error.

Return type:

ErrorEnvelope

Returns:

A frozen ErrorEnvelope suitable for serialisation to the machine-readable stderr payload.

Parameters:
render_error_text(error, *, context=None)[source]

Render the human-readable stderr payload for error.

Return type:

str

Parameters:
render_error_json(error, *, context=None, trace_id=None, active_profile=None)[source]

Serialize error to a deterministic single-line JSON document.

The document carries the shared envelope spine (schema_version, command, active_profile, status, notices) so it is shape-compatible with the success core.json_contract.SchemaEnvelope. The error detail is nested under error. command is None: the CLI error boundary terminates before the dotted command path is resolvable, so the field is present-but-null for spine uniformity. active_profile is the human label of the active taxpayer profile (the identity anchor), None for a non-profile-bound failure or when the CLI error boundary cannot resolve it; the core layer never scans profile manifests, so the CLI boundary resolves the label and passes it here. The core.json_contract.ENVELOPE_SCHEMA_VERSION import is function-local to avoid the json_contract <-> errors import cycle (json_contract imports AeatError).

Return type:

str

Parameters:
get_error_exit_code(category)[source]

Return the canonical process exit code for category.

The exit-code family is the operator’s coarse outcome signal:

  • ERROR -> 1: an expected, operator-actionable failure or refusal of a domain outcome. A modelo verification that resolves not-granted — whether BLOCKED (a blocking-rule finding) or INCOMPLETE (missing required casillas) — exits 1: both are expected verification verdicts, surfaced through typer.Exit(code=1) in the verify handler, never as an INTERNAL crash.

  • REFUSED -> 2, AUTH -> 3, INTEGRITY -> 4, FAIL -> 5, LOCKED -> 7: the remaining expected, registered refusal classes.

  • INTERNAL -> 6 is reserved exclusively for an unexpected internal crash (the INTERNAL_* registry codes: INTERNAL_CLI_UNEXPECTED_BOUNDARY, INTERNAL_WORKFLOW_UNHANDLED, etc.). An expected domain outcome MUST NOT map to INTERNAL — a not-granted verification verdict is a result the operator must act on, not a program defect, so it never exits 6.

Return type:

int

Parameters:

category (ErrorCategory)

resolve_error_message(error, code=None)[source]

Resolve the user-facing message for error.

translated_message is a translation key (e.g. "profile.errors.not_configured") by convention; it is rendered through the i18n backend, which falls back to the key itself when no matching translation exists.

Return type:

str

Parameters:
get_error_suggestion(error, code=None)[source]

Resolve the copy-paste recovery command for error.

Return type:

str | None

Parameters: