kovidgoyal/kitty · error
Too many nested include directives while processing config f
Error message
Too many nested include directives while processing config file: %s
What it means
The config file parser limits include directives to 32 levels of nesting to prevent infinite recursion. When parsing an include chain deeper than 32 files, it aborts with this error naming the file being processed.
Source
Thrown at tools/config/api.go:128
}
return os.Getenv(k)
})
}
const OverridesFileName = "<overrides>"
func (self *ConfigParser) parse(scanner Scanner, name, base_path_for_includes string, depth int) error {
if self.seen_includes[name] { // avoid include loops
return nil
}
self.seen_includes[name] = true
if self.AllIncludedFiles != nil && name != OverridesFileName {
self.AllIncludedFiles.Add(name)
}
recurse := func(r io.Reader, nname, base_path_for_includes string) error {
if depth > 32 {
return fmt.Errorf("Too many nested include directives while processing config file: %s", name)
}
escanner := bufio.NewScanner(r)
return self.parse(escanner, nname, base_path_for_includes, depth+1)
}
make_absolute := func(path string) (string, error) {
if path == "" {
return "", fmt.Errorf("Empty include paths not allowed")
}
if !filepath.IsAbs(path) {
path = filepath.Join(base_path_for_includes, path)
}
return path, nil
}
lnum := 0
next_line_num := 0
next_line := ""View on GitHub (pinned to 6d5d0c4406)
Solutions
- Check the named file and trace its include chain for a cycle
- Flatten the include hierarchy by inlining deeply nested includes
- Use the AllIncludedFiles set / logs to identify which files form the loop and break it
Example fix
# before # a.conf include b.conf # b.conf include a.conf # after # a.conf include b.conf # b.conf map ctrl+a>1 load_config_file
Defensive patterns
Strategy: validation
Validate before calling
seen := map[string]bool{}
var check func(path string, depth int) error
check = func(path string, depth int) error {
if depth > 32 { return fmt.Errorf("include chain too deep at %s", path) }
if seen[path] { return fmt.Errorf("circular include at %s", path) }
seen[path] = true
return nil // recurse into included files similarly
} Prevention
- Lint configs for include cycles before deployment
- Keep include graphs shallow; prefer one level of shared snippets
When it happens
Trigger: A chain of config files where each includes the next (directly or cyclically) exceeding depth 32, e.g. a.conf includes b.conf includes c.conf ... or two files that include each other.
Common situations: Circular includes (file A includes B which includes A), or over-modularized configs where shared snippets include other snippets repeatedly.
Related errors
- Empty include paths not allowed
- Could not find included config file: {val}, ignoring
- Could not read from included config file: {}, ignoring
- This should be run as kitten broadcast
- No option named: {k}
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/b86ad02e28c4e8e8.
Report an issue: GitHub.