Skip to content

Fetch layer: Go --frozen re-downloads on a warm cache; TS --lock pins one platform; TS ArtifactError isn't a ChtypesError; Python index.json duplicates (measured, 1.0.2) #487

Description

@EricAndrechek

Four smaller fetch-layer defects found by the same cache audit as #481, #482 and #486. Measured on the published 1.0.2 packages unless marked.

1. Go: fetch --frozen re-downloads the layer on a warm cache

  • Measured with a logging mirror: chtypes fetch 26.8 --frozen --lock L, run against a cache where that build is already installed.
    • Go: 3 requests and 42.5 MB on every run.
    • Python: 0 requests.
    • TypeScript: 1 request (a 477-byte manifest).
  • Cause (inferred): Go's frozen path (go/internal/ocifetch/ensure.go, the frozen branch) never checks the installed record by the pinned manifest digest.
  • Fix: check the installed record first, as Python does. Zero requests when the pinned build is installed and verified.

2. TypeScript: fetch --lock pins only the host platform

  • Measured: a lock written by the TypeScript CLI pins only the platform it ran on. Go and Python pin all three platforms.
  • The consequence: a lock written on a Mac cannot drive a --frozen fetch in a Linux image; that fails with ARTIFACT_PINNED.
  • Spec: docs/guides/fetch-v1.md §6 requires a written lock to pin every platform.
  • Fix: pin all platforms. The conformance case that should catch this needs checking: either it does not reach the CLI's lock-writing path, or TypeScript passes it through a different path.

3. TypeScript: ArtifactError is not a ChtypesError

  • Measured: new ArtifactMissingError('x') instanceof ChtypesError is false. In Python the artifact errors are ChtypesErrors.
  • The consequence: a TypeScript caller that catches ChtypesError to handle every SDK error misses the artifact errors.
  • Fix: make ArtifactError extend ChtypesError, as the other bindings' hierarchies do. It changes the public class hierarchy, so it is weighed against the public-surface parity gate (a v1 public-surface parity gate #436).

4. Python: index.json gains duplicate entries

  • Measured: 8 concurrent Python installs of one build left 7 or 8 entries for the SAME digest in the layout's index.json.
  • Cause: the merge appends without deduplicating (python/src/chtypes/_ocifetch/_ensure.py).
  • Impact: harmless to chtypes, which never trusts index.json alone, but untidy for other OCI tools reading the layout.
  • Fix: deduplicate by digest, as Go and TypeScript do.

Items 1, 2 and 4 are binding code with tests, and can ship in a 1.0.x. Item 3 waits for #436 if it counts as an API change.

🤖 Generated with Claude Code

Activity

  1. EricAndrechek commented on Oct 10, 2026

    @EricAndrechek
    MemberAuthor

    Fixed on v2 by #606 (merge cfcc8799), all four bindings, each re-measured on v2 first:

    1. Go fetch --frozen on a warm cache made 3 requests (manifest, layer, bundle); now 0. The installed record is checked by the pinned digests first.
    2. TS --lock now pins every platform by default, as the other bindings do.
    3. TS ArtifactError now extends ChtypesError, a breaking class-hierarchy change with codes and messages unchanged (TS CHANGELOG, ### Changed).
    4. Python index.json no longer gets a second entry for one manifest.

    Pinned by the conformance case frozen-warm-cache-zero-requests (requests.max 0) and per-binding tests. It ships in the next 2.0.0-dev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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