dagger/dagger · error

illegal exclusion pattern: "!"

Error message

illegal exclusion pattern: "!"

What it means

After trimming and filepath.Clean, a pattern consisting solely of '!' would be an exclusion of nothing — meaningless and likely a typo. NewPattern detects this case and returns a dedicated error instead of constructing a Pattern that excludes nothing.

Source

Thrown at util/patternmatcher/patternmatcher.go:290

	cleanedPattern string
	dirs           []string
	regexp         *regexp.Regexp
	exclusion      bool
}

var ErrEmptyPattern = errors.New("empty pattern")

func NewPattern(p string) (*Pattern, error) {
	// Eliminate leading and trailing whitespace.
	p = strings.TrimSpace(p)
	if p == "" {
		return nil, ErrEmptyPattern
	}
	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:]
	}
	// 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))

	return newp, nil
}

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Remove the bare '!' line from the pattern list or ignore file
  2. If you meant to exclude something, put a path after the '!', e.g. '!keep.txt'
  3. Check template/variable expansion so the exclusion path isn't interpolated to empty
  4. Filter out or validate patterns of length 1 before passing them to the matcher

Example fix

// before (.dockerignore)
!
// after
!Dockerfile
Defensive patterns

Strategy: validation

Validate before calling

func validExclusion(p string) bool {
	p = strings.TrimSpace(p)
	return !(p == "!" || strings.TrimSpace(strings.TrimPrefix(p, "!")) == "")
}

Type guard

func isBareExclusion(p string) bool { return strings.TrimSpace(p) == "!" }

Try / catch

p, err := NewPattern(raw)
if err != nil && strings.Contains(err.Error(), "illegal exclusion pattern") {
	// skip or report the malformed '!' line
}

Prevention

When it happens

Trigger: Calling NewPattern("!"), NewPattern(" ! "), or passing "!" as one of the patterns to New or Glob.

Common situations: A .dockerignore line containing just '!'; a script or template that interpolated an empty value after the '!' prefix (e.g. '!${EXCLUDE}') leaving a bare '!'; a user misunderstanding exclusion syntax.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/7ae36b302cf45b40. Report an issue: GitHub.