GoogleContainerTools/skaffold · error
invalid glob pattern: %w
Error message
invalid glob pattern: %w
What it means
expandSrcGlobPatterns expands each COPY source pattern with filepath.Glob; Go's Glob returns an ErrBadPattern for malformed patterns (the only realistic case is an unterminated character class like '['), and Skaffold wraps that as 'invalid glob pattern'. This is a caller-side path-pattern problem, not a Dockerfile syntax problem.
Source
Thrown at pkg/skaffold/docker/parse.go:224
return nil
}
func expandSrcGlobPatterns(workspace string, cpCmds []*copyCommand) ([]FromTo, error) {
var fts []FromTo
for _, cpCmd := range cpCmds {
matchesOne := false
for _, p := range cpCmd.srcs {
path := filepath.Join(workspace, p)
if _, err := os.Stat(path); err == nil {
fts = append(fts, FromTo{From: filepath.Clean(p), To: cpCmd.dest, ToIsDir: cpCmd.destIsDir, StartLine: cpCmd.startLine, EndLine: cpCmd.endLine})
matchesOne = true
continue
}
files, err := filepath.Glob(path)
if err != nil {
return nil, fmt.Errorf("invalid glob pattern: %w", err)
}
if files == nil {
continue
}
for _, f := range files {
rel, err := filepath.Rel(workspace, f)
if err != nil {
return nil, fmt.Errorf("getting relative path of %s", f)
}
fts = append(fts, FromTo{From: rel, To: cpCmd.dest, ToIsDir: cpCmd.destIsDir, StartLine: cpCmd.startLine, EndLine: cpCmd.endLine})
}
matchesOne = true
}
if !matchesOne {
return nil, fmt.Errorf("file pattern %s must match at least one file", cpCmd.srcs)View on GitHub (pinned to a1189de023)
Solutions
- Escape literal brackets in filenames, e.g. COPY app\[1\] /app, or rename the file to avoid brackets
- Balance the character class: app[12] is valid glob syntax
- Check the inner wrapped error — filepath.ErrBadPattern always means an unterminated '['
- Prefer passing literal paths without glob metacharacters when no pattern matching is needed
Example fix
// before (Dockerfile) COPY build/app[1 /app // after COPY build/app\[1\] /app
Defensive patterns
Strategy: validation
Validate before calling
func patternsAreValidGlobs(srcs []string) error {
for _, s := range srcs {
if _, err := filepath.Glob(filepath.Join(workspace, s)); err != nil {
return fmt.Errorf("COPY source %q is not a valid glob: %w", s, err)
}
}
return nil
}
// cheap pre-check: unbalanced '['
func balancedBrackets(s string) bool { return strings.Count(s, "[") == strings.Count(s, "]") } Type guard
func isValidGlobPattern(p string) bool {
_, err := filepath.Glob(p)
return err == nil
} Try / catch
fts, err := skaffold.ReadCopyCmdsFromDockerfile(path, args, cfg, false)
if err != nil && strings.Contains(err.Error(), "invalid glob pattern") {
return fmt.Errorf("escape literal '[' in COPY sources or balance the class: %w", err)
} Prevention
- Escape '[' and ']' in filenames that contain them literally
- Prefer explicit paths over globs when matching is not needed
- Add a CI check that runs filepath.Glob on every COPY source extracted from your Dockerfiles
- Avoid regex-style patterns — Dockerfile COPY sources are Go globs, not regex
When it happens
Trigger: A COPY/ADD source in the Dockerfile (after glob expansion against the workspace) contains an unbalanced '[' with no matching ']', e.g. COPY app[1 /app, reached via ReadCopyCmdsFromDockerfile.
Common situations: Filenames containing literal '[' bracket characters (common with generated/compiled artifacts) that were not escaped; someone writing regex-style patterns instead of glob syntax; accidental truncation of a pattern string.
Related errors
- getting relative path of %s
- file pattern %s must match at least one file
- glob: %w
- invalid exclude patterns: %w
- failed to evaluate pod name pattern %q due to error %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/ed0a1d1e750dea33.
Report an issue: GitHub.