{"record":{"id":"b86ad02e28c4e8e8","repo":"kovidgoyal/kitty","slug":"too-many-nested-include-directives-while-processin","errorCode":null,"errorMessage":"Too many nested include directives while processing config file: %s","messagePattern":"Too many nested include directives while processing config file: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/config/api.go","lineNumber":128,"sourceCode":"\t\t}\n\t\treturn os.Getenv(k)\n\t})\n}\n\nconst OverridesFileName = \"<overrides>\"\n\nfunc (self *ConfigParser) parse(scanner Scanner, name, base_path_for_includes string, depth int) error {\n\tif self.seen_includes[name] { // avoid include loops\n\t\treturn nil\n\t}\n\tself.seen_includes[name] = true\n\tif self.AllIncludedFiles != nil && name != OverridesFileName {\n\t\tself.AllIncludedFiles.Add(name)\n\t}\n\n\trecurse := func(r io.Reader, nname, base_path_for_includes string) error {\n\t\tif depth > 32 {\n\t\t\treturn fmt.Errorf(\"Too many nested include directives while processing config file: %s\", name)\n\t\t}\n\t\tescanner := bufio.NewScanner(r)\n\t\treturn self.parse(escanner, nname, base_path_for_includes, depth+1)\n\t}\n\n\tmake_absolute := func(path string) (string, error) {\n\t\tif path == \"\" {\n\t\t\treturn \"\", fmt.Errorf(\"Empty include paths not allowed\")\n\t\t}\n\t\tif !filepath.IsAbs(path) {\n\t\t\tpath = filepath.Join(base_path_for_includes, path)\n\t\t}\n\t\treturn path, nil\n\t}\n\n\tlnum := 0\n\tnext_line_num := 0\n\tnext_line := \"\"","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/config/api.go#L110-L146","documentation":"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.","triggerScenarios":"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.","commonSituations":"Circular includes (file A includes B which includes A), or over-modularized configs where shared snippets include other snippets repeatedly.","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"],"exampleFix":"# before\n# a.conf\ninclude b.conf\n# b.conf\ninclude a.conf\n# after\n# a.conf\ninclude b.conf\n# b.conf\nmap ctrl+a>1 load_config_file","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nvar check func(path string, depth int) error\ncheck = func(path string, depth int) error {\n    if depth > 32 { return fmt.Errorf(\"include chain too deep at %s\", path) }\n    if seen[path] { return fmt.Errorf(\"circular include at %s\", path) }\n    seen[path] = true\n    return nil // recurse into included files similarly\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint configs for include cycles before deployment","Keep include graphs shallow; prefer one level of shared snippets"],"tags":["config","include","recursion","kitty"],"backgroundTag":"config-circular-include","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}