Files
at-container-registry/pkg/appview
Evan JarrettandClaude Opus 5 1631898005 appview: give every Repository() error an OCI code instead of 500 {}
A user with an unresolvable defaultHold (did:web:localhost%3A8080) got HTTP
500 with a body of literally {} on every request in their namespace, and
crane retried it three times because 500 is retryable.

The cause is in the distribution library. handlers/app.go:755 switches on the
error type returned by Repository() with cases for ErrRepositoryUnknown,
ErrRepositoryNameInvalid and errcode.Error, and no default. A bare fmt.Errorf
matches none of them, so context.Errors stays empty; ServeJSON then finds no
ErrorCoder, leaves sc == 0, falls through to 500, and Errors.MarshalJSON
renders the nil slice as {} via omitempty.

So every error leaving Repository() must be coded. Four were not:

  hold URL unresolvable  -> 404 NAME_UNKNOWN when errors.Is
                            atproto.ErrHoldDIDPermanent, else 503 UNAVAILABLE
  no hold DID configured -> 500 UNKNOWN, but with a body and a log line
  invalid image name     -> 400 NAME_INVALID
  name missing an owner  -> 400 NAME_INVALID

The permanent/transient split is the point: a DNS blip must stay retryable,
but a did:web that can never resolve must not be retried at all. Stored user
data that cannot resolve is a 4xx condition, not a server fault, and the
NAME_UNKNOWN message now names the hold so the owner can fix their profile.
The hold DID is already world-readable in their sailor profile record.

Tests assert through a helper that replays distribution's exact type switch,
so an uncoded error still surfaces as 500 {} and the assertions bind to the
real behaviour rather than to the constructors.

Does not address the logrus line at app.go:757, which fires unconditionally
before the type switch and cannot be avoided by any returned error type.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PDqoCE1j3njokkZ9b1C5n9
2026-09-02 21:02:40 -05:00
..
2026-05-09 21:21:20 -05:00
2026-01-04 22:39:48 -06:00
2026-01-06 23:56:17 -06:00
2026-02-03 20:35:13 -06:00