GoogleContainerTools/skaffold · error

getting hash for %q: %w

Error message

getting hash for %q: %w

What it means

The inputDigest Tagger hashes the artifact's build dependencies to derive a deterministic tag. For each dependency file it opens/hashes the file; if hashing a file fails for a reason other than the file not existing (which is skipped), the error is wrapped as 'getting hash for %q:'.

Source

Thrown at pkg/skaffold/tag/input_digest.go:82

	if image.KanikoArtifact != nil {
		srcFiles = append(srcFiles, image.KanikoArtifact.DockerfilePath)
	}

	if image.CustomArtifact != nil && image.CustomArtifact.Dependencies != nil && image.CustomArtifact.Dependencies.Dockerfile != nil {
		srcFiles = append(srcFiles, image.CustomArtifact.Dependencies.Dockerfile.Path)
	}

	// must sort as hashing is sensitive to the order in which files are processed
	sort.Strings(srcFiles)
	for _, d := range srcFiles {
		h, err := fileHasher(d, image.Workspace)
		if err != nil {
			if os.IsNotExist(err) {
				log.Entry(ctx).Tracef("skipping dependency %q for artifact cache calculation: %v", d, err)
				continue // Ignore files that don't exist
			}

			return "", fmt.Errorf("getting hash for %q: %w", d, err)
		}
		inputs = append(inputs, h)
	}

	return encode(inputs)
}

func encode(inputs []string) (string, error) {
	// get a key for the hashes
	hasher := sha256.New()
	enc := json.NewEncoder(hasher)
	if err := enc.Encode(inputs); err != nil {
		return "", err
	}
	return hex.EncodeToString(hasher.Sum(nil)), nil
}

// fileHasher hashes the contents and name of a file

View on GitHub (pinned to a1189de023)

Solutions

  1. Fix permissions on the dependency file (chmod/chown so the build user can read it)
  2. Remove or correct the offending dependency path in skaffold.yaml build.artifacts.dependencies
  3. Re-run after syncing the workspace — the file may have been deleted concurrently
  4. Point dependencies at regular files, not directories or broken symlinks

Example fix

// before
dependencies:
  - paths: ["secrets.key"]   # mode 0600, owned by root
// after
sudo chmod a+r secrets.key   # or list a readable copy in dependencies
Defensive patterns

Strategy: validation

Validate before calling

for _, d := range artifact.Dependencies {
    if _, err := os.Stat(d); os.IsPermission(err) || isDir(d) {
        return fmt.Errorf("dependency %q unreadable or not a regular file", d)
    }
}

Try / catch

tag, err := tagger.GenerateTag(ctx, image)
var pathErr error
if errors.As(err, &pathErr) {
    return fmt.Errorf("check permissions/existence of dependency files: %w", err)
}

Prevention

When it happens

Trigger: GenerateTag on an artifact whose dependency paths include a file that exists in the dependency list but cannot be opened/hashed: permission-denied, a path that is a directory, a broken symlink, or an I/O error while reading.

Common situations: Dependencies declared in skaffold.yaml pointing to paths with wrong permissions in CI; a dependency listed as a directory or glob that resolves oddly; files deleted between listing and hashing in a concurrently modified workspace.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/f3d32280084345ea. Report an issue: GitHub.