GoogleContainerTools/skaffold · error
reading .dockerignore: %w
Error message
reading .dockerignore: %w
What it means
SyncMap fails with "reading .dockerignore" when readDockerignore cannot read the .dockerignore file that sits next to the resolved Dockerfile. Skaffold treats a present-but-unreadable .dockerignore as fatal for computing syncable files (a missing file is usually ignored; IO errors like permission denied are not).
Source
Thrown at pkg/skaffold/docker/syncmap.go:47
// SyncMap creates a map of syncable files by looking at the COPY/ADD commands in the Dockerfile.
// All keys are relative to the Skaffold root, the destinations are absolute container paths.
// TODO(corneliusweig) destinations are not resolved across stages in multistage dockerfiles. Is there a use-case for that?
func SyncMap(ctx context.Context, workspace string, dockerfilePath string, buildArgs map[string]*string, cfg Config) (map[string][]string, error) {
absDockerfilePath, err := NormalizeDockerfilePath(workspace, dockerfilePath)
if err != nil {
return nil, fmt.Errorf("normalizing dockerfile path: %w", err)
}
// only the COPY/ADD commands from the last image are syncable
fts, err := ReadCopyCmdsFromDockerfile(ctx, true, absDockerfilePath, workspace, buildArgs, cfg)
if err != nil {
return nil, err
}
excludes, err := readDockerignore(workspace, absDockerfilePath)
if err != nil {
return nil, fmt.Errorf("reading .dockerignore: %w", err)
}
srcByDest, err := walkWorkspaceWithDestinations(workspace, excludes, fts)
if err != nil {
return nil, fmt.Errorf("walking workspace: %w", err)
}
return invertMap(srcByDest), nil
}
// walkWorkspaceWithDestinations walks the given host directories and determines their
// location in the container. It returns a map of host path by container destination.
// Note: if you change this function, you might also want to modify `WalkWorkspace`.
func walkWorkspaceWithDestinations(workspace string, excludes []string, fts []FromTo) (map[string]string, error) {
dockerIgnored, err := NewDockerIgnorePredicate(workspace, excludes)
if err != nil {
return nil, err
}View on GitHub (pinned to a1189de023)
Solutions
- Check that .dockerignore next to the Dockerfile is a regular file: `file .dockerignore`; delete it if it's a directory.
- Fix permissions: `chmod u+r .dockerignore` or chown to the running user.
- Remove or repair broken symlinks pointing at missing targets.
- If the file is unnecessary, delete it so readDockerignore takes the missing-file path.
- Verify disk health/space if the error indicates an underlying IO failure.
Example fix
// before $ ls -l .dockerignore drwxr-xr-x 2 root root .dockerignore # accidentally a directory // after $ rm -rf .dockerignore && printf 'node_modules\n.git\n' > .dockerignore && chmod u+r .dockerignore
Defensive patterns
Strategy: validation
Validate before calling
func checkDockerignore(workspace, dockerfilePath string) error {
dir := filepath.Dir(dockerfilePath)
if !filepath.IsAbs(dir) { dir = filepath.Join(workspace, dir) }
p := filepath.Join(dir, ".dockerignore")
fi, err := os.Stat(p)
if os.IsNotExist(err) { return nil } // absent is fine
if err != nil { return err }
if !fi.Mode().IsRegular() { return fmt.Errorf("%s is not a regular file", p) }
f, err := os.Open(p)
if err != nil { return fmt.Errorf("%s unreadable: %w", p, err) }
f.Close()
return nil
} Type guard
func dockerignoreReadable(workspace, df string) bool { return checkDockerignore(workspace, df) == nil } Try / catch
if _, err := docker.SyncMap(ctx, workspace, dockerfilePath, buildArgs, cfg); err != nil {
if strings.Contains(err.Error(), "reading .dockerignore") {
return fmt.Errorf("ensure .dockerignore next to %s is a readable regular file (or delete it): %v", dockerfilePath, err)
}
return err
} Prevention
- Ensure .dockerignore is a regular file, never a directory or dangling symlink.
- Set read permissions for the user running Skaffold/CI (watch for root-created files in containers).
- If .dockerignore is unnecessary, omit it entirely rather than committing an empty stub with bad perms.
When it happens
Trigger: A .dockerignore exists next to the Dockerfile but is a directory, has no read permission, or an IO error occurs while opening/reading it during SyncMap.
Common situations: .dockerignore created as a directory by mistake; restrictive permissions after copying files in a container/CI with root ownership; a symlink pointing to a nonexistent target; disk/IO failures.
Related errors
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/fbe9e89d8a1e952c.
Report an issue: GitHub.