Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/navigation.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
15 changes: 15 additions & 0 deletions getting_started/artifacts.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ 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.

<Warning>
**`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 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.

See [repo digest unavailable](/troubleshooting/repo_digest_unavailable) for more detail.
</Warning>

See [kosli attest artifact](/client_reference/kosli_attest_artifact/) for more details.


Expand Down
53 changes: 53 additions & 0 deletions troubleshooting/repo_digest_unavailable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
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}}' <image>
```

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 <registry>/<image>:<tag>
kosli attest artifact <registry>/<image>:<tag> --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 <registry>/<image>:<tag> \
--artifact-type=oci \
--registry-username=$REGISTRY_USER \
--registry-password=$REGISTRY_TOKEN \
...
```

### Provide the fingerprint directly

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.