{"record":{"id":"ac78b10f8b5abfbd","repo":"GoogleContainerTools/skaffold","slug":"file-pattern-s-must-match-at-least-one-file","errorCode":null,"errorMessage":"file pattern %s must match at least one file","messagePattern":"file pattern (.+?) must match at least one file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/docker/parse.go","lineNumber":242,"sourceCode":"\t\t\t\treturn nil, fmt.Errorf(\"invalid glob pattern: %w\", err)\n\t\t\t}\n\t\t\tif files == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfor _, f := range files {\n\t\t\t\trel, err := filepath.Rel(workspace, f)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"getting relative path of %s\", f)\n\t\t\t\t}\n\n\t\t\t\tfts = append(fts, FromTo{From: rel, To: cpCmd.dest, ToIsDir: cpCmd.destIsDir, StartLine: cpCmd.startLine, EndLine: cpCmd.endLine})\n\t\t\t}\n\t\t\tmatchesOne = true\n\t\t}\n\n\t\tif !matchesOne {\n\t\t\treturn nil, fmt.Errorf(\"file pattern %s must match at least one file\", cpCmd.srcs)\n\t\t}\n\t}\n\n\tlog.Entry(context.TODO()).Debugf(\"Found dependencies for dockerfile: %v\", fts)\n\n\treturn fts, nil\n}\n\nfunc extractCopyCommands(ctx context.Context, nodes []*parser.Node, onlyLastImage bool, cfg Config) ([]*copyCommand, error) {\n\tstages := map[string]bool{\n\t\t\"scratch\": true,\n\t}\n\n\tslex := shell.NewLex('\\\\')\n\tvar copied []*copyCommand\n\n\tworkdir := \"/\"\n\tenvs := make([]string, 0)","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/docker/parse.go#L224-L260","documentation":"If a COPY source pattern matched zero files anywhere in the workspace, expandSrcGlobPatterns fails with 'file pattern %s must match at least one file'. Docker's build would also fail on such a COPY, so Skaffold surfaces it early during dependency computation. The message includes the full srcs list of the failing copy command.","triggerScenarios":"ReadCopyCmdsFromDockerfile (only when onlyLastImage/all-images mode requires existing files) hits a COPY whose source path/glob has no match on disk — wrong relative directory, file not built yet, case-mismatched filename, or pattern expecting generated output that does not exist yet.","commonSituations":"Case sensitivity (README.md vs readme.md on Linux); running dependency computation before a codegen step that produces the copied files; Dockerfile written for a different workspace layout than skaffold.yaml's context; typos or stale paths after refactoring.","solutions":["cd into the workspace and verify the path in the error actually exists (ls the pattern with the shell)","Fix the COPY source path or glob in the Dockerfile to match the real file location","Run the build/codegen step that generates the missing files before Skaffold computes dependencies","Check filename case and workspace context in skaffold.yaml — the pattern is resolved relative to that context, not the repo root"],"exampleFix":"// before (Dockerfile)\nCOPY dist/bundle.js /app/\n// after (path verified against workspace)\nCOPY build/output/bundle.js /app/","handlingStrategy":"validation","validationCode":"func sourcesMatchAtLeastOneFile(workspace string, srcs []string) error {\n    for _, s := range srcs {\n        matches, err := filepath.Glob(filepath.Join(workspace, s))\n        if err != nil { return err }\n        if len(matches) == 0 {\n            return fmt.Errorf(\"COPY source %q matches no files under %s\", s, workspace)\n        }\n    }\n    return nil\n}","typeGuard":"func globMatchesSomething(workspace, pattern string) bool {\n    matches, err := filepath.Glob(filepath.Join(workspace, pattern))\n    return err == nil && len(matches) > 0\n}","tryCatchPattern":"fts, err := skaffold.ReadCopyCmdsFromDockerfile(path, args, cfg, false)\nif err != nil && strings.Contains(err.Error(), \"must match at least one file\") {\n    var srcs string\n    fmt.Sscanf(err.Error(), \"file pattern %s must match\", &srcs)\n    return fmt.Errorf(\"verify path exists under workspace (case-sensitive) or run codegen first: %s\", srcs)\n}","preventionTips":["Verify every COPY source with ls/glob from inside the workspace before building","Check filename case — Linux resolution is case-sensitive","Run codegen/build steps that produce copied artifacts before Skaffold dependency extraction","After refactoring directory layouts, grep Dockerfiles for stale source paths"],"tags":["dockerfile-copy","file-not-found","glob"],"backgroundTag":"dockerfile-copy-source-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"}