{"record":{"id":"fbe9e89d8a1e952c","repo":"GoogleContainerTools/skaffold","slug":"reading-dockerignore-w-fbe9e8","errorCode":null,"errorMessage":"reading .dockerignore: %w","messagePattern":"reading \\.dockerignore: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/docker/syncmap.go","lineNumber":47,"sourceCode":"\n// SyncMap creates a map of syncable files by looking at the COPY/ADD commands in the Dockerfile.\n// All keys are relative to the Skaffold root, the destinations are absolute container paths.\n// TODO(corneliusweig) destinations are not resolved across stages in multistage dockerfiles. Is there a use-case for that?\nfunc SyncMap(ctx context.Context, workspace string, dockerfilePath string, buildArgs map[string]*string, cfg Config) (map[string][]string, error) {\n\tabsDockerfilePath, err := NormalizeDockerfilePath(workspace, dockerfilePath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"normalizing dockerfile path: %w\", err)\n\t}\n\n\t// only the COPY/ADD commands from the last image are syncable\n\tfts, err := ReadCopyCmdsFromDockerfile(ctx, true, absDockerfilePath, workspace, buildArgs, cfg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\texcludes, err := readDockerignore(workspace, absDockerfilePath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading .dockerignore: %w\", err)\n\t}\n\n\tsrcByDest, err := walkWorkspaceWithDestinations(workspace, excludes, fts)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"walking workspace: %w\", err)\n\t}\n\n\treturn invertMap(srcByDest), nil\n}\n\n// walkWorkspaceWithDestinations walks the given host directories and determines their\n// location in the container. It returns a map of host path by container destination.\n// Note: if you change this function, you might also want to modify `WalkWorkspace`.\nfunc walkWorkspaceWithDestinations(workspace string, excludes []string, fts []FromTo) (map[string]string, error) {\n\tdockerIgnored, err := NewDockerIgnorePredicate(workspace, excludes)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/docker/syncmap.go#L29-L65","documentation":"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).","triggerScenarios":"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.","commonSituations":".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.","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."],"exampleFix":"// before\n$ ls -l .dockerignore\ndrwxr-xr-x 2 root root .dockerignore   # accidentally a directory\n// after\n$ rm -rf .dockerignore && printf 'node_modules\\n.git\\n' > .dockerignore && chmod u+r .dockerignore","handlingStrategy":"validation","validationCode":"func checkDockerignore(workspace, dockerfilePath string) error {\n\tdir := filepath.Dir(dockerfilePath)\n\tif !filepath.IsAbs(dir) { dir = filepath.Join(workspace, dir) }\n\tp := filepath.Join(dir, \".dockerignore\")\n\tfi, err := os.Stat(p)\n\tif os.IsNotExist(err) { return nil } // absent is fine\n\tif err != nil { return err }\n\tif !fi.Mode().IsRegular() { return fmt.Errorf(\"%s is not a regular file\", p) }\n\tf, err := os.Open(p)\n\tif err != nil { return fmt.Errorf(\"%s unreadable: %w\", p, err) }\n\tf.Close()\n\treturn nil\n}","typeGuard":"func dockerignoreReadable(workspace, df string) bool { return checkDockerignore(workspace, df) == nil }","tryCatchPattern":"if _, err := docker.SyncMap(ctx, workspace, dockerfilePath, buildArgs, cfg); err != nil {\n\tif strings.Contains(err.Error(), \"reading .dockerignore\") {\n\t\treturn fmt.Errorf(\"ensure .dockerignore next to %s is a readable regular file (or delete it): %v\", dockerfilePath, err)\n\t}\n\treturn err\n}","preventionTips":["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."],"tags":["docker","dockerignore","filesystem","permissions"],"backgroundTag":"file-read-permission","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}