cli/cli · error

failed to write attestation: %v

Error message

failed to write attestation: %v

What it means

Thrown by `gh attestation download` when the local metadata store (LiveStore.createMetadataFile) fails to write the .jsonl bundle file for the downloaded attestations. This is a local filesystem failure after a successful API fetch: file creation, JSON marshalling, writing, or closing failed (the wrapped error says which).

Source

Thrown at pkg/cmd/attestation/download/download.go:164

			fmt.Fprintf(opts.Logger.IO.Out, "No attestations found for %s\n", opts.ArtifactPath)
			return nil
		}
		return fmt.Errorf("failed to fetch attestations: %v", err)
	}

	// Apply predicate type filter to returned attestations
	if opts.PredicateType != "" {
		filteredAttestations, err := api.FilterAttestations(opts.PredicateType, attestations)
		if err != nil {
			return fmt.Errorf("failed to filter attestations: %v", err)
		}

		attestations = filteredAttestations
	}

	metadataFilePath, err := opts.Store.createMetadataFile(artifact.DigestWithAlg(), attestations)
	if err != nil {
		return fmt.Errorf("failed to write attestation: %v", err)
	}
	fmt.Fprintf(opts.Logger.IO.Out, "Wrote attestations to file %s.\nAny previous content has been overwritten\n\n", metadataFilePath)

	fmt.Fprint(opts.Logger.IO.Out,
		opts.Logger.ColorScheme.Greenf(
			"The trusted metadata is now available at %s\n", metadataFilePath,
		),
	)

	return nil
}

View on GitHub (pinned to 0eeec0b92e)

Solutions

  1. Check the wrapped message to see which step failed (create/marshall/write/close)
  2. Ensure the output directory exists and is writable: mkdir -p <dir> && touch <dir>/test
  3. If -O was passed, verify the path; otherwise ensure the current directory is writable
  4. Free disk space or fix permissions and rerun

Example fix

# before
gh attestation download ./artifact.bin -O /readonly/dir
# after
mkdir -p ./attestations && gh attestation download ./artifact.bin -O ./attestations
Defensive patterns

Strategy: validation

Validate before calling

dir := "."
if opts.OutputPath != "" { dir = opts.OutputPath }
info, err := os.Stat(dir)
if err != nil || !info.IsDir() || info.Mode().Perm()&0200 == 0 {
	return fmt.Errorf("output dir %q missing or not writable", dir)
}

Try / catch

path, err := store.createMetadataFile(digest, attestations)
if err != nil {
	return fmt.Errorf("persist attestations for %s: %w", digest, err)
}

Prevention

When it happens

Trigger: os.Create on the output path fails (unwritable directory, permission denied, invalid path on Windows due to colons in the digest), json.Marshal of a bundle fails, f.Write fails (disk full), or f.Close fails.

Common situations: Using -O/--output-dir pointing to a read-only or nonexistent directory, running without write permission in the current directory, or a digest-derived filename containing characters the filesystem rejects.

Related errors


AI-assisted analysis of cli/cli@0eeec0b92e (2026-08-15). Data as JSON: /api/errors/32a8e9df24db39a1. Report an issue: GitHub.