air-verse/air · error
build.rules[%d] (%s): at least one of include_dir, include_e
Error message
build.rules[%d] (%s): at least one of include_dir, include_ext or include_file is required
What it means
normalizeRules requires each `build.rules` entry to declare at least one matcher — include_dir, include_ext, or include_file — otherwise the rule could never match anything and is rejected. The error names the rule index and name.
Source
Thrown at runner/config.go:180
func (r *cfgRule) delay() time.Duration {
if r.Delay <= 0 {
return 1000 * time.Millisecond
}
return time.Duration(r.Delay) * time.Millisecond
}
func (c *cfgBuild) normalizeRules(root string) error {
for i := range c.Rules {
r := &c.Rules[i]
if r.Name == "" {
r.Name = fmt.Sprintf("rule-%d", i)
}
if r.Cmd == "" {
return fmt.Errorf("build.rules[%d] (%s): cmd is required", i, r.Name)
}
if len(r.IncludeDir) == 0 && len(r.IncludeExt) == 0 && len(r.IncludeFile) == 0 {
return fmt.Errorf("build.rules[%d] (%s): at least one of include_dir, include_ext or include_file is required", i, r.Name)
}
r.includeDirAbs = r.includeDirAbs[:0]
for _, dir := range r.IncludeDir {
dir = cleanPath(dir)
if dir == "" {
continue
}
abs := filepath.Clean(dir)
if !filepath.IsAbs(abs) {
abs = filepath.Join(root, abs)
}
r.includeDirAbs = append(r.includeDirAbs, filepath.Clean(abs))
}
r.regexCompiled = r.regexCompiled[:0]
for _, expr := range r.ExcludeRegex {
re, err := regexp.Compile(expr)
if err != nil {
return fmt.Errorf("build.rules[%d] (%s): failed to compile regex %q: %w", i, r.Name, expr, err)View on GitHub (pinned to 71ea1dee05)
Solutions
- Add at least one matcher, e.g. include_ext = [".go"] or include_dir = ["cmd"]
- Delete the rule if it is not needed
- Check for typos in the include_* key names
Example fix
// before (.air.toml) [[build.rules]] name = "tests" cmd = "go test ./..." // after (.air.toml) [[build.rules]] name = "tests" cmd = "go test ./..." include_ext = ["_test.go"]
Defensive patterns
Strategy: validation
Validate before calling
# each rules block must set include_dir, include_ext or include_file grep -A5 '^\\[\\[build.rules\\]\\]' .air.toml | grep -Eq 'include_(dir|ext|file)' || echo "rule missing include_*"
Prevention
- Always pair a rule's cmd with at least one include_* matcher
- Watch for typos in include_dir/include_ext/include_file keys
- Delete unused rules instead of leaving empty stubs
When it happens
Trigger: Loading a `.air.toml` whose `[[build.rules]]` has a cmd but none of include_dir / include_ext / include_file set (all empty arrays or absent).
Common situations: Writing a rule with only cmd and name and forgetting the matcher; commenting out the include_ext line; mispelling the key (e.g. include_ex) so it parses as empty.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- build.rules[%d] (%s): cmd is required
- build.rules[%d] (%s): failed to compile regex %q: %w
- configuration already exists
- entrypoint values must be strings, got %T
- entrypoint must be a string or array of strings, got %T
AI-assisted analysis of air-verse/air@71ea1dee05 (2026-08-31).
Data as JSON: /api/errors/bad88d904487fab7.
Report an issue: GitHub.