{"record":{"id":"8d642c37bd69b600","repo":"projectdiscovery/nuclei","slug":"include-directive-exceeded-maximum-include-depth-o","errorCode":null,"errorMessage":"include directive exceeded maximum include depth of %d","messagePattern":"include directive exceeded maximum include depth of (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/utils/yaml/preprocess.go","lineNumber":139,"sourceCode":"\nfunc readIncludedFile(includeFileName string, includeStack map[string]struct{}, depth int) ([]byte, error) {\n\tincludePath := includePathKey(includeFileName)\n\tif _, ok := includeStack[includePath]; ok {\n\t\treturn nil, fmt.Errorf(\"circular include directive detected: %s\", includeFileName)\n\t}\n\n\tincludeStack[includePath] = struct{}{}\n\tdefer delete(includeStack, includePath)\n\n\tincludeFileContent, err := os.ReadFile(includeFileName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// if it's yaml, tries to preprocess that too recursively\n\tif stringsutil.HasSuffixAny(includeFileName, extensions.YAML) {\n\t\tif depth >= maxIncludeDepth {\n\t\t\treturn nil, fmt.Errorf(\"include directive exceeded maximum include depth of %d\", maxIncludeDepth)\n\t\t}\n\t\tincludeFileContent, err = preProcess(includeFileContent, includeFileName, includeStack, depth+1)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn includeFileContent, nil\n}\n\nfunc includePathKey(includeFileName string) string {\n\tincludePath, err := filepath.Abs(includeFileName)\n\tif err != nil {\n\t\treturn filepath.Clean(includeFileName)\n\t}\n\tif evaluatedPath, err := filepath.EvalSymlinks(includePath); err == nil {\n\t\treturn evaluatedPath\n\t}","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/utils/yaml/preprocess.go#L121-L157","documentation":"The YAML preprocessor refuses to recurse past 32 levels of nested include directives. When an included file is itself YAML, readIncludedFile recursively preprocesses it; before recursing it checks depth >= maxIncludeDepth (a hard-coded constant of 32) and fails fast. This is a runaway-include guard — normal templates are only a few levels deep.","triggerScenarios":"A chain of YAML files each including the next that reaches 32 nesting levels; combined with a cycle that varies paths (e.g. generated filenames) so the circular-include check never fires; a script that auto-generates include files and keeps appending.","commonSituations":"Machine-generated template trees, deeply chained shared-credential or payload files, or an accidental self-include through a copy of the file under a different name (cycle detection keys on absolute path, so renamed copies evade it while depth keeps growing).","solutions":["Flatten the include chain: move the deepest content up or merge files so nesting stays well under 32.","Look for a rename-induced pseudo-cycle (file X includes a copy of itself under another name/path) and remove the duplicate.","If you genuinely need more than 32 levels, restructure — the limit is intentional; raise maxIncludeDepth only as a last-resort fork.","Audit generated includes: run the preprocessor on the root file and print the include chain as it descends."],"exampleFix":"# before: a1 includes a2 includes a3 ... includes a33 (33 files)\n# -> include directive exceeded maximum include depth of 32\n\n# after: merge a20..a33 into a single 'tail.yaml' so total depth <= 20\ninclude: a19.yaml\n# a19.yaml\ninclude: tail.yaml","handlingStrategy":"validation","validationCode":"// assert nesting stays shallow before running\nfunc includeDepth(root string) (int, error) { /* walk include directives, return max depth */ }","typeGuard":null,"tryCatchPattern":"if _, err := yamlutil.Preprocess(raw, path); err != nil {\n    if strings.Contains(err.Error(), \"maximum include depth\") {\n        // structural defect: flatten the tree, do not retry\n    }\n}","preventionTips":["Keep include trees under ~5 levels; 32 is a runaway guard, not a budget.","Beware self-include via renamed copies (cycle detection uses absolute paths).","Generate-and-audit: if includes are machine-produced, log the chain while descending."],"tags":["yaml","include","template","depth-limit"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}