slimtoolkit/slim · error

illegal exclusion pattern: "!"

Error message

illegal exclusion pattern: "!"

What it means

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.

Source

Thrown at pkg/docker/dockerignore/dockerignore.go:148

	patterns   []*pattern
	exclusions bool
}

func newPatternMatcher(patterns []string) (*patternMatcher, error) {
	pm := &patternMatcher{
		patterns: make([]*pattern, 0, len(patterns)),
	}
	for _, p := range patterns {
		// Eliminate leading and trailing whitespace.
		p = strings.TrimSpace(p)
		if p == "" {
			continue
		}
		p = filepath.Clean(p)
		newp := &pattern{}
		if p[0] == '!' {
			if len(p) == 1 {
				return nil, errors.New("illegal exclusion pattern: \"!\"")
			}
			newp.exclusion = true
			p = p[1:]
			pm.exclusions = true
		}
		// Do some syntax checking on the pattern.
		// filepath's Match() has some really weird rules that are inconsistent
		// so instead of trying to dup their logic, just call Match() for its
		// error state and if there is an error in the pattern return it.
		// If this becomes an issue we can remove this since its really only
		// needed in the error (syntax) case - which isn't really critical.
		if _, err := filepath.Match(p, "."); err != nil {
			return nil, err
		}
		newp.cleanedPattern = p
		newp.dirs = strings.Split(p, string(os.PathSeparator))
		pm.patterns = append(pm.patterns, newp)
	}

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Edit the .dockerignore (or pattern list) and remove the standalone '!' line.
  2. If a negation was intended, append the path after it, e.g. '!node_modules/important.txt'.
  3. Add a pre-parse check that skips or rejects lines where p == "!" after trimming.
  4. Lint .dockerignore files in CI to catch malformed negation patterns.

Example fix

// before (.dockerignore)
node_modules
!
// after
node_modules
!node_modules/.keep
Defensive patterns

Strategy: validation

Validate before calling

cleaned := strings.TrimSpace(line)
if cleaned == "!" {
    return fmt.Errorf("bare '!' exclusion in pattern list line %d", i)
}

Try / catch

patterns, err := dockerignore.Parse(parsedLines)
// or catch at Match time:
if err != nil {
    if strings.Contains(err.Error(), "illegal exclusion pattern") {
        // point user to the offending .dockerignore line
    }
    return err
}

Prevention

When it happens

Trigger: Calling dockerignore Match (which builds a patternMatcher via newPatternMatcher) with a pattern list containing a line that is exactly "!".

Common situations: 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.

Related errors


AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31). Data as JSON: /api/errors/df31aac4b1eff5a5. Report an issue: GitHub.