# Attestation is not supported for the docker driver

> Attestation is not supported for the docker driver is one of four separate refusals. Find which program refused your provenance or SBOM build.

Source: https://latchkey.dev/learn/docker/docker-provenance-sbom-attestation-unsupported  
Updated: 2026-09-21

Attestation is not supported for the docker driver is buildx telling you the builder you are on cannot carry attestations at all, which is a different refusal from the exporter one people usually conflate with it. Four separate programs refuse attestation builds with four different sentences, and the default provenance buildx adds on its own is not any of them.

## What this error means

A build that worked stops as soon as `--provenance` or `--sbom` is set, or a `--load` that worked stops when someone turns attestations on. The wording depends on which program objected: buildx refuses before the build starts and prints three lines with a documentation link, while BuildKit refuses at export time with one line about manifest lists. The block below is two builds on this machine, one per driver.

```Captured locally on Docker 29.6.2 and buildx v0.35.0-desktop.2, 2026-09-21
--- docker buildx build --provenance=true --load, on the default docker driver
ERROR: failed to build: Attestation is not supported for the docker driver.
Switch to a different driver, or turn on the containerd image store, and try again.
Learn more at https://docs.docker.com/go/attestations/
--- the same flag on a docker-container builder, refused later and by a different program
ERROR: failed to build: docker exporter does not currently support exporting manifest lists
```

## Common causes

### You asked for attestations on a driver that cannot carry them

The default `docker` driver without the containerd image store does not report multi platform support, and buildx requires that feature before it will pass any attestation through. It refuses at the flag rather than letting the build run and fail late, which is the right call and also why the message mentions a driver rather than your Dockerfile.

### A non inline attestation turned a single platform build into an index

This is the case that actually produces the exporter message. `--provenance=mode=max` and any `--sbom` write attestation manifests, which means the result is an index with more than one ref. The docker exporter refuses an index, so a `--load` fails at the end of an otherwise successful build. The refusal itself is the sentence we captured, from a multi platform load that reaches it the same way.

### You are loading a multi platform build

Nothing to do with attestations, and it produces the identical exporter sentence, which is why the two get conflated. A `--platform linux/amd64,linux/arm64 --load` gives you "docker exporter does not currently support exporting manifest lists" with no attestation flags anywhere. If your build sets both, remove the platforms first and see whether the message survives.

### The BuildKit daemon behind your builder is older than 0.11.0

Attestations arrived in BuildKit 0.11.0, and buildx checks for the capability rather than the version number. When the driver supports multi platform but the daemon does not advertise the attestation capability, you get "Attestations are not supported by the current BuildKit daemon" instead. In CI this usually means a pinned builder image or a self hosted buildkitd nobody has upgraded.

### You forced Docker media types on an export that carries attestations

Attestation manifests can only be described in OCI media types, so setting `oci-mediatypes=false` on an export that has them is a contradiction and BuildKit says so directly. This tends to appear when someone fixes a registry compatibility problem with a media type flag and a supply chain requirement adds attestations later.

## How to fix it

### Decide whether you need the artifact loaded or pushed

1. If the image is only being scanned or tested in the same job, `--load` is what you want and attestations are not.
2. If the image is being published, push it: the registry exporter handles indexes, so attestations and multiple platforms are both fine.
3. Do not try to have both in one invocation. Build twice if you genuinely need a local image and an attested published one.

```.github/workflows/build.yml
- uses: docker/build-push-action@v7
  with:
    context: .
    load: true
    provenance: false
    sbom: false
    tags: acme/api:ci

- uses: docker/build-push-action@v7
  with:
    context: .
    push: true
    provenance: mode=max
    sbom: true
    tags: ghcr.io/acme/api:1.4.2
```

### Turn on the containerd image store if you want attestations on the docker driver

This is what the message itself suggests, and it is the only way to keep the plain driver and still carry attestations, because the classic image store cannot hold an index. On a hosted runner it means configuring the daemon before the build step, which is a real cost; on a self hosted runner image it is a one time change.

```daemon.json
# /etc/docker/daemon.json on the runner image
{
  "features": { "containerd-snapshotter": true }
}
```

> The daemon has to be restarted for this to take effect, so it belongs in the runner image rather than in a workflow step.

### Keep the default provenance and drop only what forces an index

Since the default is inline only, you do not have to give up provenance to make `--load` work. Leave the defaults alone and set only the flags that create separate manifests. This keeps the build metadata that ends up in the image configuration while avoiding the exporter refusal.

```Terminal
# loads, and still carries the default inline provenance
docker buildx build --load -t acme/api:ci .

# refuses at the exporter, because mode=max writes its own manifest
docker buildx build --provenance=mode=max --load -t acme/api:ci .
```

### Turn the defaults off globally only when you mean it

There is an environment variable that stops buildx adding its default provenance. Reach for it when a registry or a downstream tool genuinely cannot cope with the inline metadata, not as a reflex, because it is a supply chain signal you are giving up for every build in that job.

```.github/workflows/build.yml
env:
  BUILDX_NO_DEFAULT_ATTESTATIONS: 1
```

## How to prevent it

- Split loading and publishing into two build invocations with different flags rather than one that has to satisfy both.
- Pin the builder image behind your `docker-container` driver so the attestation capability does not change under a job.
- Record which of your registries accept OCI indexes, because the exporter message will not tell you later.
- Treat `--load` in CI as a testing convenience and push everything you intend to keep.

## Four refusals that people treat as one

Two of these come from buildx, before any build starts, and two from BuildKit, at the moment it tries to write the result. They fail at different times, they name different things, and the fix for one is not the fix for another. Identify yours from the wording before you change a flag.

The buildx one is assembled at runtime from a feature name, the name of your driver and a documentation URL, so the sentence you pasted exists as a literal in no source file. Searching for it will not find the code; searching for "is not supported for the" and the word driver will.

| The sentence you got | Which program refused | When it refused |
| --- | --- | --- |
| Attestation is not supported for the <name> driver. | buildx, its not-supported helper | Before the build, from a driver feature check |
| Attestations are not supported by the current BuildKit daemon | buildx, its build option assembly | Before the build, when the daemon lacks the capability |
| docker exporter does not currently support exporting manifest lists | BuildKit, the image exporter | At export, when the result has more than one ref |
| cannot export attestations with "oci-mediatypes=false" | BuildKit, the container image writer | At export, when you forced Docker media types |

> Read in docker/buildx (build/utils.go and build/opt.go) and moby/buildkit at commit 99bd9de (exporter/oci/export.go and exporter/containerimage/writer.go) on 2026-09-21.

## The default provenance does not break --load, and we checked both drivers

It is widely repeated that buildx attaches provenance by default and that this is why `--load` fails. The first half is true with conditions and the second half is not. When you do not pass `--provenance` and the builder supports attestations, buildx sets a provenance attestation with `mode=min` and `inline-only=true`. Inline only means it goes into the image configuration rather than into a manifest of its own, so nothing becomes an index and the docker exporter has one ref to write.

On the plain `docker` driver buildx does not add it at all, because the default attestation is only added when the driver reports the multi platform feature. So a `--load` with no attestation flags has a single ref to write on either driver and the exporter takes it. What moves the boundary is the flags that write attestation manifests of their own: `--provenance=mode=max`, and any `--sbom`, since there is no inline form of one. Each of those makes the result an index, and an index is what the docker exporter refuses. The boundary is non inline attestations, not attestations in general.

| Build | Builder driver | Result |
| --- | --- | --- |
| `--load`, no attestation flags | `docker` | Loaded |
| `--provenance=true --load` | `docker` | Attestation is not supported for the docker driver. |
| `--load`, no attestation flags | `docker-container` | Loaded |
| `--provenance=mode=max --load` | `docker-container` | docker exporter does not currently support exporting manifest lists |
| `--sbom=true --load` | `docker-container` | docker exporter does not currently support exporting manifest lists |

> Two rows are captured locally on this machine on 2026-09-21, Docker 29.6.2 with buildx v0.35.0-desktop.2, and kept in our transcript: the docker driver refusal, and the exporter sentence, which we captured from a multi platform `--load` that reaches it by the same route. The other three rows are read from the buildx and BuildKit source cited above rather than measured, and either is repeatable on your own machine in under a minute.

## Which driver your workflow is on decides which sentence you can get

A job that never calls `docker/setup-buildx-action` is on the `docker` driver, which is BuildKit inside the daemon. That driver reports no multi platform support unless the containerd image store is on, so it cannot carry attestations and buildx stops you at the flag. A job that does call the setup action is on a `docker-container` builder, which can, so the same flags get you all the way to the exporter before anything objects.

This is why the same workflow changes its error message when someone adds a setup step for an unrelated reason. Neither message is about your Dockerfile, and the fix in each case is on the output, not on the image.

```.github/workflows/build.yml
# on the docker driver: attestations are refused at the flag
- run: docker buildx build --provenance=true --load .

# after this, the same build reaches the exporter instead
- uses: docker/setup-buildx-action@v4
- run: docker buildx build --provenance=true --load .
```

## Why no recorded run backs this page

Every claim on this page is a decision made by a flag and a driver feature bit, and any of the five combinations can be run locally in under a minute. A Latchkey run would add the observation that a hosted runner also has a `docker` driver until you install a builder, which is true and is one sentence, not a recorded job.

The part that would have needed a runner is a claim about what happens on GitHub hosted infrastructure specifically, and this page does not make one. What it makes instead is a claim about buildx and BuildKit, which are the same binaries wherever they run, and it shows the five outcomes in a table, marking which two we captured and which three we read from source, so you can repeat any of them on your own machine.

## FAQ

### Does buildx add provenance to my builds by default?

It adds a provenance attestation with mode set to min and inline only set to true, but only when the driver reports multi platform support. On the plain docker driver it adds nothing. Inline only means the metadata goes into the image configuration rather than a separate manifest, which is why the default does not stop a load.

### Why does --sbom break --load when --provenance does not?

Because there is no inline form of an SBOM. Any SBOM attestation is written as its own manifest, which makes the result an index, and the docker exporter refuses an index. The default provenance avoids that by living in the image configuration.

### What is the difference between the driver message and the exporter message?

The driver message comes from buildx before the build starts and means this builder cannot carry attestations at all. The exporter message comes from BuildKit at the end and means the build succeeded but its result cannot be written in the format you asked for. The first is fixed by changing builder, the second by changing output.

### Do I have to give up provenance to publish to an old registry?

Often yes, because attestation manifests require OCI media types and BuildKit will tell you directly that it cannot export attestations with Docker media types forced. Treat that as a concession to one destination rather than a default, and keep attestations on for registries that accept them.

## References

- [buildx: the helper that assembles the not-supported sentence](https://github.com/docker/buildx/blob/master/build/utils.go)
- [buildx: where the default provenance attestation is set](https://github.com/docker/buildx/blob/master/build/opt.go)
- [BuildKit: the exporter that refuses a manifest list](https://github.com/moby/buildkit/blob/master/exporter/oci/export.go)
- [Docker docs: build attestations](https://docs.docker.com/build/metadata/attestations/)
- [pantsbuild/pants#21372: the exporter message on a multi platform load](https://github.com/pantsbuild/pants/issues/21372)

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
