From cf093d8e869df051cb7a825de1a2d3677097cba8 Mon Sep 17 00:00:00 2001 From: Alex Kantor Date: Tue, 28 Apr 2026 14:40:27 +0100 Subject: [PATCH 1/2] docs: clarify docker artifact-type registry requirement Customer hit "repo digest unavailable" in CI after kosli attest artifact with --artifact-type=docker. The constraint that the image must have been pushed to or pulled from a registry was only implicit in the existing copy. Add a Warning callout on the artifacts page covering the constraint and alternatives, plus a dedicated troubleshooting page for the error message. Co-Authored-By: Claude Opus 4.7 (1M context) --- config/navigation.json | 1 + getting_started/artifacts.md | 17 ++++++ troubleshooting/repo_digest_unavailable.md | 63 ++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 troubleshooting/repo_digest_unavailable.md diff --git a/config/navigation.json b/config/navigation.json index e65e4ff..171cb9d 100644 --- a/config/navigation.json +++ b/config/navigation.json @@ -122,6 +122,7 @@ "pages": [ "troubleshooting/what_do_i_do_if_kosli_is_down", "troubleshooting/docker_api_version_error", + "troubleshooting/repo_digest_unavailable", "troubleshooting/zsh_no_such_user", "troubleshooting/github_kosli_api_token", "troubleshooting/subshell_stderr", diff --git a/getting_started/artifacts.md b/getting_started/artifacts.md index fec2c5c..f41d5ce 100644 --- a/getting_started/artifacts.md +++ b/getting_started/artifacts.md @@ -44,6 +44,23 @@ The `--artifact-type` flag is used to determine the type of artifact being attes - **docker**: for docker images that are pulled on the machine. This option depends on having a running Docker daemon on the machine. - **oci**: for container images in docker or OCI format. The fingerprint is fetched directly from the registry. + +**`docker` requires the image to exist in a registry.** Kosli reads the image's repo digest via the local Docker daemon, and a freshly built image (just `docker build`) does not have one until it has been pushed to or pulled from a registry. If you attest an image that has only been built locally, you will see: + +``` +Error: repo digest unavailable for the image, has it been pushed to or pulled from a registry? +``` + +You have a few options: + +- Push the image to a registry first, then attest it. +- Use `--artifact-type=oci` and let Kosli fetch the digest directly from the registry. +- Use `--artifact-type=dir` against the build context to fingerprint the source instead. +- Compute the fingerprint yourself and pass `--fingerprint` directly. + +See [repo digest unavailable](/troubleshooting/repo_digest_unavailable) for more detail. + + See [kosli attest artifact](/client_reference/kosli_attest_artifact/) for more details. diff --git a/troubleshooting/repo_digest_unavailable.md b/troubleshooting/repo_digest_unavailable.md new file mode 100644 index 0000000..6ce4692 --- /dev/null +++ b/troubleshooting/repo_digest_unavailable.md @@ -0,0 +1,63 @@ +--- +title: "Repo digest unavailable" +description: 'How to fix the "repo digest unavailable for the image" error when running kosli attest artifact with --artifact-type=docker.' +--- + +## Error + +``` +Error: repo digest unavailable for the image, has it been pushed to or pulled from a registry? +``` + +## Why this happens + +When `kosli attest artifact` is called with `--artifact-type=docker`, Kosli asks the local Docker daemon for the image's **repo digest** (the SHA256 of the image manifest in a registry). A repo digest is only attached to an image once it has been pushed to or pulled from a registry. A freshly built image (just `docker build`) has an image ID, but no repo digest, and Kosli will refuse to attest it. + +This often surfaces in CI even when the same command appears to work locally. Locally, the image may have been pushed or pulled at some earlier point and the digest is cached on the machine. On a fresh CI runner, the image is only ever built, so the digest is genuinely missing. + +You can confirm the difference with: + +```bash +docker inspect --format '{{json .RepoDigests}}' +``` + +A built-but-never-pushed image returns `[]`. An image pulled from or pushed to a registry returns one or more digest entries. + +## Solutions + +Pick whichever fits your pipeline best. + +### Push the image first, then attest + +```bash +docker push /: +kosli attest artifact /: --artifact-type=docker ... +``` + +This is the most direct fix and produces an attestation tied to the registry digest. + +### Use `--artifact-type=oci` + +If the image is already in a registry, `oci` fetches the digest directly via the registry API and does not require a local Docker daemon at all: + +```bash +kosli attest artifact /: \ + --artifact-type=oci \ + --registry-username=$REGISTRY_USER \ + --registry-password=$REGISTRY_TOKEN \ + ... +``` + +### Fingerprint the source directory instead + +If you want the attestation to be deterministic from the source rather than dependent on the registry, use `--artifact-type=dir` against the build context: + +```bash +kosli attest artifact ./build-context --artifact-type=dir ... +``` + +The fingerprint is then a SHA256 of the directory contents and is identical regardless of where (or whether) the image is pushed. + +### Provide the fingerprint directly + +If you have already computed a fingerprint elsewhere in your pipeline, pass it with `--fingerprint` and drop `--artifact-type` entirely. From b388da107bae3786ecf8e65d5f473e490b6abebc Mon Sep 17 00:00:00 2001 From: Alex Kantor Date: Tue, 28 Apr 2026 16:12:06 +0100 Subject: [PATCH 2/2] docs: drop dir as a fix for repo digest unavailable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Source-dir fingerprinting only works as an end-to-end identity if the runtime side also fingerprints the source dir. Standard Kosli runtime reporters (K8s, ECS, Lambda, S3, etc.) fingerprint the running image, so a dir-fingerprinted attestation never links to runtime — the attested artifact and the running artifact end up as separate rows in Kosli with no provenance trail between them. Push and oci are the only safe answers for users running standard docker workflows hitting this error. Drop dir from the alternatives in both the artifacts page Warning and the troubleshooting page. Co-Authored-By: Claude Opus 4.7 (1M context) --- getting_started/artifacts.md | 4 +--- troubleshooting/repo_digest_unavailable.md | 12 +----------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/getting_started/artifacts.md b/getting_started/artifacts.md index f41d5ce..8c79db9 100644 --- a/getting_started/artifacts.md +++ b/getting_started/artifacts.md @@ -51,12 +51,10 @@ The `--artifact-type` flag is used to determine the type of artifact being attes Error: repo digest unavailable for the image, has it been pushed to or pulled from a registry? ``` -You have a few options: +You have two options: - Push the image to a registry first, then attest it. - Use `--artifact-type=oci` and let Kosli fetch the digest directly from the registry. -- Use `--artifact-type=dir` against the build context to fingerprint the source instead. -- Compute the fingerprint yourself and pass `--fingerprint` directly. See [repo digest unavailable](/troubleshooting/repo_digest_unavailable) for more detail. diff --git a/troubleshooting/repo_digest_unavailable.md b/troubleshooting/repo_digest_unavailable.md index 6ce4692..257075a 100644 --- a/troubleshooting/repo_digest_unavailable.md +++ b/troubleshooting/repo_digest_unavailable.md @@ -48,16 +48,6 @@ kosli attest artifact /: \ ... ``` -### Fingerprint the source directory instead - -If you want the attestation to be deterministic from the source rather than dependent on the registry, use `--artifact-type=dir` against the build context: - -```bash -kosli attest artifact ./build-context --artifact-type=dir ... -``` - -The fingerprint is then a SHA256 of the directory contents and is identical regardless of where (or whether) the image is pushed. - ### Provide the fingerprint directly -If you have already computed a fingerprint elsewhere in your pipeline, pass it with `--fingerprint` and drop `--artifact-type` entirely. +If you have already computed a fingerprint elsewhere in your pipeline, pass it with `--fingerprint` and drop `--artifact-type` entirely. The fingerprint must still match what runtime reporters will see for the artifact in your environments, so it should normally be the registry digest.