Skip to content

fillNamespacedBoxes silently drops an ENTIRE namespace's candy set + box views when one remote fetch fails #53

Open

Description

@aitrawog

Symptom

A project whose only content is an import: of the cachyos namespace validates with confusing
"remote candy … not found" errors for candies that do exist — and loses EVERY namespaced box view
at the same time, not just the one bad ref.

Measured on this host, charly box validate over a project importing
@github.com/opencharly/distro-cachyos:v2026.281.1001:

$ charly box validate ; echo "rc=$?"
charly: error: command "validate": 2 validation errors:

 kind:local "cachyos.charly-cachyos-app": remote candy "@github.com/opencharly/pod-dsh/candy/dsh:v2026.279.1210" not found (candy "dsh" doesn't exist in github.com/opencharly/pod-dsh)
 kind:local "cachyos.charly-cachyos-app": remote candy "@github.com/opencharly/pod-dsh/candy/dsh-tui:v2026.279.1210" not found (candy "dsh-tui" doesn't exist in github.com/opencharly/pod-dsh)
rc=1

Mechanism

fillNamespacedBoxes (candy/plugin-build/resolve_legs.go, pinned v0.2026309.2032) computes the
namespace's downloads and then folds the namespace's scan result ONLY when the scan did not error:

downloads, _ := loaderkit.CollectRemoteRefsOpts(
        sub, loaderkit.FinalizeScannedCandies(scanned, nil), spec.WithLocalRawRefs(opts, scanned),
        loaderkit.RefsSeamsFromExecutor(ctx, ex))
if nsLayers, err := loaderkit.ScanCandyFromLocal(scanned, ic, namespaceScanSeams(ctx, ex, downloads, distroCfg, stderrWarn)); err == nil {
        for name, c := range nsLayers { … rp.CandyModels[name] = m … }
        deploykit.FillNamespaceBoxViews(sub, nsLayers, ic, child, cv, d, vopts, rp)
}

ScanCandyFromLocal aborts the WHOLE fix-point on the first failed download/scan, so ONE
unresolvable pin anywhere in the namespace discards the entire namespace's candy set and box views.
The error is thrown away (err == nil, downloads, _), so validate cannot name the real cause and
instead reports everything the namespace would have supplied as missing.

Instrumented run (SDK488_DEBUG prints added to a scratch sdk checkout, then reverted) shows the
actual failure — an unrelated stale pin, not the dsh refs:

DEBUG CREO cfg=… locals=1 namespaces=1 boxes=26
DEBUG CREO local template "charly-cachyos-app"
DEBUG CREO cfg=… done pairs=202
DEBUG SCFL local=18 downloads=202 err=<nil>
DEBUG SCFL DOWNLOAD-ERR github.com/opencharly/pod-crabbox:v2026.274.0652: InvokeProvider refs:refs op=resolve: resolving github.com/opencharly/pod-crabbox:v2026.274.0652: could not resolve ref "v2026.274.0652" in https://github.com/opencharly/pod-crabbox.git

Trigger (measured)

The failing pin is real and unresolvable today:

$ grep -rn "pod-crabbox" --include=*.yml distro-cachyos/  # v2026.281.1001
box/crabbox-e2e/charly.yml:9:            - '@github.com/opencharly/pod-crabbox:v2026.274.0652'

$ gh api repos/opencharly/pod-crabbox/git/refs/tags/v2026.274.0652
{"message":"Not Found", …}  (HTTP 404)

$ git ls-remote --tags https://github.com/opencharly/pod-crabbox.git | sed 's#.*refs/tags/##' | grep -v '\^{}' | sort -V | head -1
v2026.307.1759

Missed control

No gate runs charly box validate (or loads the resolved-project envelope) over a project that
imports each distro namespace, so a namespace-local defect reddens only at a downstream consumer —
here charly check run check-pod-overlay, whose image-build step runs charly box build and dies
before building. And because the scan error is discarded, the failure is misattributed to whatever
the namespace's templates reference.

Blast radius

Every consumer importing a namespace that has ONE unresolvable remote pin silently loses the
namespace's entire candy set AND its box views. validate reports an arbitrary subset of template
refs as missing; build/check fail before the image stage. Measured: a minimal project whose only
content is import: cachyos.

Root fix

  1. plugin-build: propagate the namespace scan error — as a spec.Diagnostic on the tolerant
    (OpValidate) path, and as a hard error on the build path — instead of dropping the namespace.
    Do not discard CollectRemoteRefsOpts's error either.
  2. distro-cachyos: bump or drop @github.com/opencharly/pod-crabbox:v2026.274.0652 in
    box/crabbox-e2e/charly.yml; the tag no longer exists on the remote.

Related: opencharly/sdk#488 is the SEPARATE collector gap (a namespace's kind:local remote refs
never entered the ROOT fetch set); its fix makes the root scan materialize those refs and is why
the minimal project above validates once that fix is applied. This issue remains: the namespaced
scan still silently discards an entire namespace on any single failure.

Agent: containerd-crabbox-program/sdk488 · session 8b1c01cf-7f79-4a75-bff8-240415a06208
Assisted-by: Claude Code deepseek-v4.1-flash:cloud (fully tested and validated)

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions