{"record":{"id":"ace0241bfc140ee1","repo":"GoogleContainerTools/skaffold","slug":"normalizing-dockerfile-path-w-ace024","errorCode":null,"errorMessage":"normalizing dockerfile path: %w","messagePattern":"normalizing dockerfile path: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/docker/syncmap.go","lineNumber":36,"sourceCode":"\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\n\t\"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/util\"\n\t\"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/walk\"\n)\n\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","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/docker/syncmap.go#L18-L54","documentation":"SyncMap fails with \"normalizing dockerfile path\" when NormalizeDockerfilePath cannot resolve the Dockerfile path relative to the workspace — typically the file does not exist at workspace/dockerfilePath and isn't reachable via a remote URL. Skaffold requires an absolute, readable Dockerfile before parsing COPY/ADD commands for file sync.","triggerScenarios":"SyncMap called with a dockerfilePath that doesn't exist under workspace; path uses wrong separators or ../ escapes outside the workspace; dockerfile configured but never committed/generated; typo in the skaffold.yaml dockerfile field.","commonSituations":"dockerfile path points at a Dockerfile in a different directory than the artifact context; file renamed (Dockerfile.dev vs Dockerfile); running Skaffold from a different cwd with a relative path; multi-module repo where the path is relative to repo root not workspace.","solutions":["Check the resolved path exists: combine workspace + dockerfilePath and verify with ls; fix the path in skaffold.yaml (dockerfile: field).","Make the dockerfile path absolute or correct relative to the artifact's workspace/context.","Ensure the Dockerfile is generated before SyncMap runs if it is produced by a build step.","Verify correct working directory when invoking Skaffold with relative paths.","Check file permissions — the file must be readable."],"exampleFix":"// before\n# skaffold.yaml\nbuild.artifacts[].docker.dockerfile: ./Dockerfile.prod  # file is actually at deploy/Dockerfile.prod\n// after\nbuild.artifacts[].docker.dockerfile: ./deploy/Dockerfile.prod","handlingStrategy":"validation","validationCode":"func dockerfileExists(workspace, dockerfilePath string) error {\n\tif strings.HasPrefix(dockerfilePath, \"http://\") || strings.HasPrefix(dockerfilePath, \"https://\") {\n\t\treturn nil // remote dockerfiles are fetched by skaffold\n\t}\n\tp := dockerfilePath\n\tif !filepath.IsAbs(p) { p = filepath.Join(workspace, p) }\n\tfi, err := os.Stat(p)\n\tif err != nil { return fmt.Errorf(\"dockerfile not found at %s\", p) }\n\tif fi.IsDir() { return fmt.Errorf(\"%s is a directory\", p) }\n\treturn nil\n}","typeGuard":"func hasReadableDockerfile(workspace, p string) bool {\n\treturn dockerfileExists(workspace, p) == nil\n}","tryCatchPattern":"if err := dockerfileExists(workspace, dockerfilePath); err != nil { return err }\nif _, err := docker.SyncMap(ctx, workspace, dockerfilePath, buildArgs, cfg); err != nil {\n\tif strings.Contains(err.Error(), \"normalizing dockerfile path\") {\n\t\treturn fmt.Errorf(\"fix `dockerfile:` path in skaffold.yaml — %v\", err)\n\t}\n\treturn err\n}","preventionTips":["Make the dockerfile field relative to the artifact's workspace/context, not the repo root, unless intended.","Verify the Dockerfile is committed/generated before running skaffold dev.","Don't rename Dockerfiles without updating skaffold.yaml.","Stat the resolved path in CI smoke tests before running Skaffold."],"tags":["docker","dockerfile","filesystem","config"],"backgroundTag":"dockerfile-not-found","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"}