Skip to content

topmark.core.errors

topmark / core / errors

Core TopMark exceptions.

This module defines Click-free exception types that may be raised from any layer of TopMark, including registry construction, file-type resolution, TOML/template document handling, and higher-level orchestration code.

Each exception carries structured ErrorContext metadata so callers can inspect machine-useful details such as the affected path, qualified key, encoding, or additional diagnostic information.

CLI commands should catch these core exceptions and translate them into user-facing CLI errors with appropriate exit codes.

Design goals
  • No Click dependency.
  • Structured context via ErrorContext.
  • Clear distinction between internal invariant failures and plausibly recoverable runtime errors.
  • Preserve the underlying cause via exception chaining (raise ... from exc).

ErrorContext dataclass

ErrorContext(
    *,
    message,
    path=None,
    qualified_key=None,
    encoding=None,
    diagnostics=None,
    resolved=None,
    details=(),
)

Structured context attached to a core TopMark error.

Attributes:

Name Type Description
message str

Human-readable error message, without CLI styling.

path Path | None

Optional filesystem path associated with the failure.

qualified_key str | None

Optional qualified key associated with the failure.

encoding str | None

Optional encoding name relevant to the failure.

diagnostics MutableDiagnosticLog | FrozenDiagnosticLog | None

Optional diagnostic log associated with the failure.

resolved ResolvedTopmarkTomlSources | None

Optional resolved TOML-side state associated with the failure.

details tuple[str, ...]

Optional tuple of additional diagnostic details.

TopmarkError

TopmarkError(context)

Bases: Exception

Base class for Click-free TopMark exceptions.

Parameters:

Name Type Description Default
context ErrorContext

Structured context describing the failure.

required
Source code in src/topmark/core/errors.py
def __init__(
    self,
    context: ErrorContext,
) -> None:
    super().__init__(context.message)
    self.context: Final[ErrorContext] = context

ReservedNamespaceError

ReservedNamespaceError(
    *, namespace, owner, entities, owner_module=None
)

Bases: TopmarkError

Raised when a reserved namespace is used by an ineligible registry entry.

This is intended for registry composition and registration APIs where the topmark namespace is reserved for built-in entities and must not be claimed by external overlays, plugins, or test fixtures unless they are defined from within the TopMark package.

Parameters:

Name Type Description Default
namespace str

Reserved namespace that was used.

required
owner str

Human-readable owner label for the offending entry.

required
entities str

Registry entity category involved in the violation.

required
owner_module str | None

Optional module path where the offending entry is defined.

None
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    namespace: str,
    owner: str,
    entities: str,
    owner_module: str | None = None,
) -> None:
    details: list[str] = [
        f"namespace={namespace}",
        f"owner={owner}",
        f"entities={entities}",
    ]
    if owner_module is not None:
        details.append(f"owner_module={owner_module}")

    message: str = (
        f"Reserved namespace violation: '{namespace}' is reserved for built-in "
        f"TopMark {entities} (owner: {owner})"
    )
    super().__init__(
        ErrorContext(
            message=message,
            details=tuple(details),
        )
    )
    self.namespace: Final[str] = namespace
    self.owner: Final[str] = owner
    self.entities: Final[str] = entities
    self.owner_module: Final[str | None] = owner_module

UnsupportedFileTypeError

UnsupportedFileTypeError(*, file_type, path=None)

Bases: TopmarkError

Raised when a file type is recognized but currently unsupported.

This distinguishes "unknown file type" from "known file type with no usable processor", which can be useful for diagnostics, reporting, and fallback handling.

Parameters:

Name Type Description Default
file_type str

Recognized file type identifier that is currently unsupported.

required
path Path | None

Optional filesystem path associated with the lookup.

None
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    file_type: str,
    path: Path | None = None,
) -> None:
    msg: str = (
        f"Unsupported file type: {file_type}"
        if path is None
        else f"Unsupported file type for {path}: {file_type}"
    )
    super().__init__(
        ErrorContext(
            message=msg,
            path=path,
            qualified_key=file_type,
        )
    )
    self.file_type: Final[str] = file_type

UnknownFileTypeError

UnknownFileTypeError(*, file_type, path=None)

Bases: TopmarkError

Raised when a file type identifier cannot be resolved from a registry.

This error is typically raised by public registry helpers when a caller references a file type identifier that is not present in the effective file type view.

Parameters:

Name Type Description Default
file_type str

File type identifier that could not be resolved.

required
path Path | None

Optional filesystem path associated with the lookup.

None
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    file_type: str,
    path: Path | None = None,
) -> None:
    msg: str = (
        f"Unknown file type identifier: {file_type}"
        if path is None
        else f"Unknown file type identifier for {path}: {file_type}"
    )
    super().__init__(
        ErrorContext(
            message=msg,
            path=path,
            qualified_key=file_type,
        )
    )
    self.file_type: Final[str] = file_type

AmbiguousFileTypeIdentifierError

AmbiguousFileTypeIdentifierError(*, file_type, candidates)

Bases: TopmarkError

Raised when an unqualified file type identifier resolves ambiguously.

This error is intended for lookup helpers that accept either unqualified or qualified file type identifiers. Callers can recover by retrying with an explicit qualified identifier of the form "<namespace>:<name>".

Parameters:

Name Type Description Default
file_type str

Unqualified file type identifier supplied by the caller.

required
candidates tuple[str, ...]

Candidate qualified keys that matched the identifier.

required
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    file_type: str,
    candidates: tuple[str, ...],
) -> None:
    message: str = (
        f"Ambiguous file type identifier: {file_type} (candidates: {', '.join(candidates)})"
    )
    super().__init__(
        ErrorContext(
            message=message,
            qualified_key=file_type,
            details=tuple(f"candidate={candidate}" for candidate in candidates),
        )
    )
    self.file_type: Final[str] = file_type
    self.candidates: Final[tuple[str, ...]] = candidates

InvalidRegistryIdentityError

InvalidRegistryIdentityError(
    *,
    message,
    identifier=None,
    namespace=None,
    local_key=None,
)

Bases: TopmarkError

Raised when a registry identifier or identity pair is malformed.

This error is intended for public registry APIs that accept identifiers such as "<local_key>" or "<namespace>:<local_key>" and need to reject malformed input explicitly rather than treating it as merely unknown.

Parameters:

Name Type Description Default
message str

Human-readable error message, without CLI styling.

required
identifier str | None

Optional raw identifier string supplied by the caller.

None
namespace str | None

Optional namespace component when available.

None
local_key str | None

Optional namespace-local identifier when available.

None
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    identifier: str | None = None,
    namespace: str | None = None,
    local_key: str | None = None,
) -> None:
    details: list[str] = []
    if identifier is not None:
        details.append(f"identifier={identifier}")
    if namespace is not None:
        details.append(f"namespace={namespace}")
    if local_key is not None:
        details.append(f"local_key={local_key}")

    super().__init__(
        ErrorContext(
            message=message,
            qualified_key=identifier or local_key,
            details=tuple(details),
        )
    )
    self.identifier: Final[str | None] = identifier
    self.namespace: Final[str | None] = namespace
    self.local_key: Final[str | None] = local_key

ProcessorBindingError

ProcessorBindingError(*, message, file_type=None)

Bases: TopmarkError

Raised when explicit processor bindings are invalid or inconsistent.

This signals a registry-construction or registry-mutation invariant failure, such as an unknown bound file type identifier, an unknown processor qualified key, or a duplicate binding declaration.

Parameters:

Name Type Description Default
message str

Human-readable error message.

required
file_type str | None

Optional file type qualified key associated with the failed binding operation.

None
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    file_type: str | None = None,
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            qualified_key=file_type,
        )
    )
    self.file_type: Final[str | None] = file_type

ProcessorRegistrationError

ProcessorRegistrationError(*, message, qualified_key)

Bases: TopmarkError

Base class for processor-registration failures.

Parameters:

Name Type Description Default
message str

Human-readable error message.

required
qualified_key str

Processor qualified key associated with the failed registration.

required
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    qualified_key: str,
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            qualified_key=qualified_key,
        )
    )
    self.qualified_key: Final[str] = qualified_key

DuplicateProcessorRegistrationError

DuplicateProcessorRegistrationError(*, qualified_key)

Bases: ProcessorRegistrationError

Raised when a processor qualified key is already registered.

This condition may be recoverable depending on caller policy, for example by unregistering or replacing the existing entry before retrying.

Parameters:

Name Type Description Default
qualified_key str

Processor qualified key that is already present in the effective registry.

required
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    qualified_key: str,
) -> None:
    super().__init__(
        message=f"Processor '{qualified_key}' is already registered.",
        qualified_key=qualified_key,
    )

DuplicateProcessorKeyError

DuplicateProcessorKeyError(
    *, qualified_key, existing_class, new_class
)

Bases: TopmarkError

Raised when multiple processor classes claim the same qualified key.

This signals an internal or overlay-composition invariant failure: the same qualified processor identity must not resolve to different processor classes in the effective processor registry.

Parameters:

Name Type Description Default
qualified_key str

Conflicting processor qualified key.

required
existing_class str

Human-readable label for the already-associated class.

required
new_class str

Human-readable label for the newly encountered class.

required
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    qualified_key: str,
    existing_class: str,
    new_class: str,
) -> None:
    message: str = (
        "Duplicate processor key detected: "
        f"{qualified_key} (classes: {existing_class} vs {new_class})"
    )
    super().__init__(
        ErrorContext(
            message=message,
            qualified_key=qualified_key,
            details=(
                f"existing_class={existing_class}",
                f"new_class={new_class}",
            ),
        )
    )
    self.qualified_key: Final[str] = qualified_key
    self.existing_class: Final[str] = existing_class
    self.new_class: Final[str] = new_class

InvalidPolicyError

InvalidPolicyError(*, message, policy_key=None)

Bases: TopmarkError

Raised when a supplied policy value is invalid or malformed.

This is intended for API-facing policy overlays and other policy parsing boundaries where invalid scalar values should be rejected explicitly.

Parameters:

Name Type Description Default
message str

Human-readable error message.

required
policy_key str | None

Optional policy key associated with the invalid value.

None
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    policy_key: str | None = None,
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            qualified_key=policy_key,
        )
    )
    self.policy_key: Final[str | None] = policy_key

InvalidReportScopeError

InvalidReportScopeError(*, message, report_value=None)

Bases: TopmarkError

Raised when a supplied report-scope value is invalid or malformed.

This is intended for API-facing reporting/view boundaries where invalid scalar values should be rejected explicitly.

Parameters:

Name Type Description Default
message str

Human-readable error message.

required
report_value str | None

Optional invalid public report-scope token.

None
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    report_value: str | None = None,
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            qualified_key=report_value,
        )
    )
    self.report_value: Final[str | None] = report_value

TomlDocumentError

TomlDocumentError(*, message, details=())

Bases: TopmarkError

Base class for TOML document parsing, rendering, and surgery errors.

This groups TOML-specific failures that arise while parsing, rendering, or structurally rewriting TOML documents.

Parameters:

Name Type Description Default
message str

Human-readable error message.

required
details tuple[str, ...]

Optional structured diagnostic details.

()
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    details: tuple[str, ...] = (),
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            details=details,
        )
    )

TomlRenderError

TomlRenderError(*, message, details=())

Bases: TomlDocumentError

Raised when TOML rendering fails due to invalid inputs or invariants.

Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    details: tuple[str, ...] = (),
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            details=details,
        )
    )

TomlParseError

TomlParseError(*, message, details=())

Bases: TomlDocumentError

Raised when a TOML document cannot be parsed.

Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    details: tuple[str, ...] = (),
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            details=details,
        )
    )

TomlSurgeryError

TomlSurgeryError(*, message, details=())

Bases: TomlDocumentError

Raised when structural TOML editing fails or required TOML shape invariants are violated.

Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    details: tuple[str, ...] = (),
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            details=details,
        )
    )

TemplateError

TemplateError(*, message, details=())

Bases: TomlDocumentError

Base class for annotated config-template editing and validation errors.

Template errors are narrower than generic TOML document errors: they refer specifically to the annotated configuration template and the presentation- preserving helpers that edit or validate it.

Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    details: tuple[str, ...] = (),
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            details=details,
        )
    )

TemplateEditError

TemplateEditError(*, message, details=())

Bases: TemplateError

Raised when annotated config-template editing fails.

Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    details: tuple[str, ...] = (),
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            details=details,
        )
    )

TemplateValidationError

TemplateValidationError(*, message, details=())

Bases: TemplateError

Raised when an annotated config-template result fails validation.

Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    message: str,
    details: tuple[str, ...] = (),
) -> None:
    super().__init__(
        ErrorContext(
            message=message,
            details=details,
        )
    )

ConfigValidationError

ConfigValidationError(
    *, validation_logs, strict, details=()
)

Bases: TopmarkError

Raised when config validation fails.

Config validity follows the staged config-loading validation semantics: TOML-source diagnostics, merged-config diagnostics, and runtime-applicability diagnostics are evaluated together. In non-strict mode, validation fails only when at least one stage contains an error diagnostic. In strict mode, validation fails when any stage contains either a warning or an error diagnostic.

This error is used for both immmutale FrozenConfig and mutable MutableConfig validation helpers.

Parameters:

Name Type Description Default
validation_logs MutableValidationLogs | FrozenValidationLogs

Staged validation logs attached to the config being validated.

required
strict bool

Effective resolved strictness used for staged config/preflight validation. This is the boolean strictness that was actually applied after TOML resolution and any CLI/API override.

required
details tuple[str, ...]

Optional structured diagnostic details.

()
Source code in src/topmark/core/errors.py
def __init__(
    self,
    *,
    validation_logs: MutableValidationLogs | FrozenValidationLogs,
    strict: bool,
    details: tuple[str, ...] = (),
) -> None:
    toml_stats: DiagnosticStats = validation_logs.toml_source.stats()
    config_stats: DiagnosticStats = validation_logs.merged_config.stats()
    runtime_stats: DiagnosticStats = validation_logs.runtime_applicability.stats()
    flattened_diagnostics: MutableDiagnosticLog | FrozenDiagnosticLog = (
        validation_logs.flattened()
    )
    message: str = (
        f"Config validation failed (strict = {strict!r}), "
        f"TOML errors: {toml_stats.n_error}, warnings: {toml_stats.n_warning};"
        f"Merged-config errors: {config_stats.n_error}, warnings: {config_stats.n_warning};"
        f"Runtime errors: {runtime_stats.n_error}, warnings: {runtime_stats.n_warning};"
    )
    super().__init__(
        ErrorContext(
            message=message,
            diagnostics=flattened_diagnostics,
            details=details,
        )
    )