{"record":{"id":"df31aac4b1eff5a5","repo":"slimtoolkit/slim","slug":"illegal-exclusion-pattern","errorCode":null,"errorMessage":"illegal exclusion pattern: \"!\"","messagePattern":"illegal exclusion pattern: \"!\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/docker/dockerignore/dockerignore.go","lineNumber":148,"sourceCode":"\tpatterns   []*pattern\n\texclusions bool\n}\n\nfunc newPatternMatcher(patterns []string) (*patternMatcher, error) {\n\tpm := &patternMatcher{\n\t\tpatterns: make([]*pattern, 0, len(patterns)),\n\t}\n\tfor _, p := range patterns {\n\t\t// Eliminate leading and trailing whitespace.\n\t\tp = strings.TrimSpace(p)\n\t\tif p == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tp = filepath.Clean(p)\n\t\tnewp := &pattern{}\n\t\tif p[0] == '!' {\n\t\t\tif len(p) == 1 {\n\t\t\t\treturn nil, errors.New(\"illegal exclusion pattern: \\\"!\\\"\")\n\t\t\t}\n\t\t\tnewp.exclusion = true\n\t\t\tp = p[1:]\n\t\t\tpm.exclusions = true\n\t\t}\n\t\t// Do some syntax checking on the pattern.\n\t\t// filepath's Match() has some really weird rules that are inconsistent\n\t\t// so instead of trying to dup their logic, just call Match() for its\n\t\t// error state and if there is an error in the pattern return it.\n\t\t// If this becomes an issue we can remove this since its really only\n\t\t// needed in the error (syntax) case - which isn't really critical.\n\t\tif _, err := filepath.Match(p, \".\"); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tnewp.cleanedPattern = p\n\t\tnewp.dirs = strings.Split(p, string(os.PathSeparator))\n\t\tpm.patterns = append(pm.patterns, newp)\n\t}","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/docker/dockerignore/dockerignore.go#L130-L166","documentation":"This error is raised by newPatternMatcher in the dockerignore matcher when a pattern line is a bare '!' with nothing after it. An exclusion pattern must exclude something; '!' alone is meaningless and rejected. It is surfaced through Match when the pattern list is compiled.","triggerScenarios":"Calling dockerignore Match (which builds a patternMatcher via newPatternMatcher) with a pattern list containing a line that is exactly \"!\".","commonSituations":"A hand-edited .dockerignore with a stray '!' on its own line; a script generating exclusion rules with a missing pattern after the negation prefix; template rendering that left an empty exclusion.","solutions":["Edit the .dockerignore (or pattern list) and remove the standalone '!' line.","If a negation was intended, append the path after it, e.g. '!node_modules/important.txt'.","Add a pre-parse check that skips or rejects lines where p == \"!\" after trimming.","Lint .dockerignore files in CI to catch malformed negation patterns."],"exampleFix":"// before (.dockerignore)\nnode_modules\n!\n// after\nnode_modules\n!node_modules/.keep","handlingStrategy":"validation","validationCode":"cleaned := strings.TrimSpace(line)\nif cleaned == \"!\" {\n    return fmt.Errorf(\"bare '!' exclusion in pattern list line %d\", i)\n}","typeGuard":null,"tryCatchPattern":"patterns, err := dockerignore.Parse(parsedLines)\n// or catch at Match time:\nif err != nil {\n    if strings.Contains(err.Error(), \"illegal exclusion pattern\") {\n        // point user to the offending .dockerignore line\n    }\n    return err\n}","preventionTips":["Lint .dockerignore in CI; reject lines that are exactly '!'.","When generating exclusions programmatically, only emit '!' followed by a non-empty pattern.","Trim whitespace and skip empty lines before matching.","Document negation syntax for users editing ignore files."],"tags":["dockerignore","pattern-matching","config"],"backgroundTag":"illegal-ignore-pattern","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}