Skip to content

Module import resolution leaks raw exceptions for invalid declarations, lock records and policy files #1580

Open

Description

@doublewhy

Problem

Several values that module import resolution reads are checked by Pydantic or the OS but never translated into the SDL error envelope. They escape as raw ValidationError, RecursionError, yaml errors, UnicodeDecodeError or IsADirectoryError, and raes sdl resolve prints a traceback. ADR-076 §5 says import and model validation "must not leak a raw Pydantic ValidationError through parser or language-service entry points", and specs/sdl/diagnostics.md §7 and §8 forbid framework input renderings and trust-policy contents in diagnostics. Probed on dev a391904a (file:line on that commit, under implementations/python/packages):

  • resolve_lock_records validates each root import with ImportDecl.model_validate (raes/module_registry/resolution.py:470). An import with version: 1.0, a missing namespace, or version: '>=banana' raises a raw ValidationError, while parse_sdl_file reports the same root as SDLParseError with an sdl.model.invalid diagnostic at /imports/0/.... raes sdl resolve (raes_cli/sdl.py:67) then exits 1 with a traceback that renders input_value=1.0.
  • resolve_lock_records accepts imports: {}, an import version: '' and a module version: '', and writes a lockfile, although parse_sdl_file rejects all three. For the two blank versions, parse_sdl_file raises a raw ValidationError from ResolvedImportProvenance (raes/_composition_provenance.py:40) instead of a diagnostic.
  • A locked: import whose lock record has requested_version: '>=banana' raises a raw ValidationError from the delegated ImportDecl (raes/module_registry/resolution.py:200-206). A record whose own source is locked:x and whose resolved_source is x, imported as locked:x, raises RecursionError, because _resolve_locked_import hands the record's source back to itself (:207). An acyclic two-record chain resolves today.
  • load_lockfile and load_trust_policy (raes/module_registry/models.py:85-86, :93) raise a raw ValidationError for invalid JSON or a wrong shape (for example registries: [1]), a yaml.parser.ParserError for bad YAML, UnicodeDecodeError for a file that is not UTF-8, and IsADirectoryError for a directory. These come through parse_sdl_file, and the trust-policy cases also through resolve_lock_records.
  • A local import that names a directory raises IsADirectoryError through both entry points (raes/module_registry/resolution.py:224-226 checks only exists()).
  • An imported unit with a removed scoring section (metrics: {}) gets the generic "/metrics: Extra inputs are not permitted" diagnostic, because _reject_removed_scoring_sections (raes/parser.py:251, called at :377) runs only for the root. ADR-073 §5 gives removed scoring surfaces a pointer to their replacement.
  • expand_sdl_modules called directly with an invalid declaration raises a raw ValidationError from _import_decl (raes/composition/_expand.py:176-179, called at :252).

Scope

  • Translate each failure above into the existing SDLParseError envelope through the existing bounded renderer (_model_parse_error), with no new exception type, model, schema or language change. Messages name the failed file or import and never render input values or OS error text.
  • resolve_lock_records validates root import declarations and the provenance record it writes the same way parse_sdl_file does, so raes sdl resolve rejects only documents parse_sdl_file already rejects. The lockfile for a valid root is unchanged.
  • The rendering of raes sdl verify-imports errors stays with Import verification ends in a traceback on a semantic error #1552.
  • The change is package code under implementations/python/packages, which the research-evidence digest covers, so both research captures are republished in the same pull request.

Done when

  • resolve_lock_records and raes sdl resolve report invalid root import declarations with the same code, pointer and range as parse_sdl_file, and reject the import sources and versions that parse_sdl_file cannot record as provenance. A valid root still gives a byte-identical lockfile.
  • An invalid locked: record, or a locked: chain that revisits a record, raises SDLParseError naming raes.lock.json. It does not raise ValidationError or RecursionError. Acyclic chains resolve as before.
  • An invalid, malformed, non-UTF-8 or directory raes.lock.json or raes-trust.yaml raises SDLParseError with the file as path and its name in the message, and never renders its values.
  • An import that names a directory gets an SDLParseError naming the import, and an imported unit with a removed scoring section gets the root's ADR-073 message.
  • expand_sdl_modules called directly reports an invalid declaration as a field diagnostic.
  • raes sdl resolve exits non-zero and prints no traceback for each of these, naming the failing file.
  • Both research captures are republished.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions