Skip to content

Skip unreadable entries in image list - #2157

Open
Hokila wants to merge 1 commit into
apple:mainfrom
Hokila:fix/2149-image-list-unreadable-entry
Open

Skip unreadable entries in image list#2157
Hokila wants to merge 1 commit into
apple:mainfrom
Hokila:fix/2149-image-list-unreadable-entry

Conversation

@Hokila

@HokilaHokila commented Aug 26, 2026

Copy link
Copy Markdown

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Motivation and Context

When one image entry has unreadable content, image list currently stops before rendering any entries. Resolve each image independently so readable images are still rendered, and log the skipped image reference and error to stderr so structured stdout remains valid.

Fixes#2149.

Testing

  • Tested locally

  • Added/updated tests

  • Added/updated docs

  • make test: 760 tests in 83 suites passed

  • make check: formatting and license checks passed

@Hokila
Hokilaforce-pushed the fix/2149-image-list-unreadable-entry branch from 3edfdd2 to fbea4e9CompareAugust 26, 2026 02:43
@Hokila

Hokila commented Aug 26, 2026

Copy link
Copy Markdown
Author

Hi @katiewasnothere, this PR is ready for review.

  • make test: 760 tests in 83 suites passed
  • make check: formatting and license checks passed
  • The commit is GitHub SSH-signed and shows as Verified

Could you please approve the pending workflow and review this PR when you have a chance? Thank you!

@Hokila
Hokilaforce-pushed the fix/2149-image-list-unreadable-entry branch from 481bf16 to bb235f9CompareAugust 27, 2026 01:47
@Hokila

Copy link
Copy Markdown
Author

@egernst
I've rebased this PR onto the latest main. Could you please rerun the workflow?
The previous failure appears to have been caused by a runner timeout, so I believe it should pass on a rerun. Thanks!

@Hokila
Hokilaforce-pushed the fix/2149-image-list-unreadable-entry branch from bb235f9 to b7be756CompareAugust 27, 2026 06:06
@jglogan

jglogan commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

@Hokila Can you add a reproduction procedure to your description to show how you're triggering the error?

That will help us determine whether the changes we merged in apple/containerization#898 resolve this issue for the 1.3.1 release.

Once we know how things behave with those changes, let's look at this PR and see what would be the best UX for handling broken resources (images in this case).

@Hokila

Copy link
Copy Markdown
Author

Thanks @jglogan. I’ll update the PR description with the exact reproduction procedure and retest it against a build that includes apple/containerization#898.

The current regression test covers per-image error isolation in the CLI, but it does not establish whether #898 already prevents or tolerates the underlying broken image-store state. I’ll document the before/after behavior once I’ve verified it with those changes.

After that, I’m happy to revisit whether the CLI-side skip-and-warn behavior is still needed and what the best UX should be for broken image resources.

@Hokila

Copy link
Copy Markdown
Author

Thanks @jglogan. I reproduced the issue using the same image-store fixture across all three versions.

Reproduction setup

Environment:

  • macOS 26, arm64
  • One healthy image: docker.io/library/alpine:latest
  • One broken image record: example.invalid/broken:latest
  • The broken record contains a syntactically valid descriptor, but its root content blob is absent.

I used an isolated application root:

$ export APP_ROOT=/tmp/container-image-list-repro
$ container system start \ --app-root "$APP_ROOT" \ --disable-kernel-install
$ container image pull docker.io/library/alpine:latest
$ container system stop

I then added the following record to $APP_ROOT/state.json without creating its referenced content blob:

{
"example.invalid/broken:latest": {
"digest": "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"size": 1,
"mediaType": "application/vnd.oci.image.index.v1+json"
}
}

The file below was intentionally absent:

$APP_ROOT/content/blobs/sha256/ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

container 1.3.0, before containerization#898

Version:

$ container --versioncontainer CLI version 1.3.0 (build: debug, commit: d96dfa3)

The default listing fails without rendering the healthy image:

$ container image listError: content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ echo$?1

JSON, YAML, and verbose output fail in the same way:

$ container image list --format jsonError: content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ echo$?1
$ container image list --format yamlError: content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ echo$?1
$ container image list --verboseError: content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ echo$?1

Quiet mode succeeds because it does not resolve the image content:

$ container image list -qalpine:latestexample.invalid/broken:latest
$ echo$?0

container 1.3.1, with containerization#898

Version:

$ container --versioncontainer CLI version 1.3.1 (build: debug, commit: a9a62e2)

The same fixture still causes the complete listing to fail:

$ container image listError: content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ echo$?1

The other detailed formats also fail:

$ container image list --format jsonError: content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ echo$?1
$ container image list --format yamlError: content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ echo$?1
$ container image list --verboseError: content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
$ echo$?1

Quiet mode remains unaffected:

$ container image list -qalpine:latestexample.invalid/broken:latest
$ echo$?0

This indicates that apple/containerization#898 does not cover this particular case. The state record itself is readable and its descriptor digest is valid; the failure occurs later when the referenced root content blob cannot be found.

With this PR

Version:

$ container --versioncontainer CLI version 1.3.0-3-gb7be756 (build: debug, commit: b7be756)

The broken image is reported, while the healthy image is still rendered:

$ container image listskipping unreadable image: ["error": notFound: "content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "image": example.invalid/broken:latest]NAME TAG DIGESTalpine latest 28bd5fe8b56d
$ echo$?0

Verbose output also succeeds:

$ container image list --verboseskipping unreadable image: ["error": notFound: "content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "image": example.invalid/broken:latest]NAME TAG INDEX DIGEST OS ARCH VARIANT FULL SIZE CREATED MANIFEST DIGESTalpine latest 28bd5fe8b56d linux amd64 3.8 MB 2026-06-16T00:01:29.967161902Z 79ff19e9084aalpine latest 28bd5fe8b56d linux arm v6 3.6 MB 2026-06-16T00:00:25.329026823Z bc301c70d7e7alpine latest 28bd5fe8b56d linux arm v7 3.3 MB 2026-06-16T00:00:26.526765088Z 48bf253520b1alpine latest 28bd5fe8b56d linux arm64 v8 4.2 MB 2026-06-16T00:01:20.474100947Z e7a1a92a5bfealpine latest 28bd5fe8b56d linux 386 3.7 MB 2026-06-16T00:01:19.360099979Z 6f5908cdf811alpine latest 28bd5fe8b56d linux ppc64le 3.8 MB 2026-06-16T00:00:15.017984356Z a30366c2d264alpine latest 28bd5fe8b56d linux riscv64 3.6 MB 2026-06-16T05:59:15.56408535Z 20a26477b54falpine latest 28bd5fe8b56d linux s390x 3.7 MB 2026-06-16T00:00:21.879382071Z 4eea4e45f63f
$ echo$?0

I also captured JSON stdout and stderr separately:

$ container image list --format json > images.json 2> warning.log
$ echo$?0
$ cat warning.logskipping unreadable image: ["image": example.invalid/broken:latest, "error": notFound: "content with digest sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]
$ jq length images.json1
$ jq -r '.[0].configuration.name' images.jsondocker.io/library/alpine:latest

This confirms that:

  1. The healthy image remains available in table, JSON, YAML, and verbose listings.
  2. The broken image and underlying error are identified in a warning.
  3. The warning is written to stderr and does not invalidate structured stdout.
  4. The listing exits successfully.
  5. containerization#898 does not independently resolve the missing-content case reproduced here.

The PR therefore fixes the listing behavior for this failure mode, although it does not repair or remove the underlying broken image resource.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: container image list fails entirely when one content blob is unreadable

2 participants

@Hokila@jglogan