{"record":{"id":"3985a23a818dd25a","repo":"projectdiscovery/nuclei","slug":"invalid-workflow-with-no-templates-or-tags","errorCode":null,"errorMessage":"invalid workflow with no templates or tags","messagePattern":"invalid workflow with no templates or tags","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/templates/workflows.go","lineNumber":29,"sourceCode":"\t\"github.com/projectdiscovery/nuclei/v3/pkg/workflows\"\n)\n\n// compileWorkflow compiles the workflow for execution\nfunc compileWorkflow(path string, preprocessor Preprocessor, options *protocols.ExecutorOptions, workflow *workflows.Workflow, loader model.WorkflowLoader) {\n\tfor _, workflow := range workflow.Workflows {\n\t\tif err := parseWorkflow(preprocessor, workflow, options, loader); err != nil {\n\t\t\tgologger.Warning().Msgf(\"Could not parse workflow %s: %v\\n\", path, err)\n\t\t\tcontinue\n\t\t}\n\t}\n}\n\n// parseWorkflow parses and compiles all templates in a workflow recursively\nfunc parseWorkflow(preprocessor Preprocessor, workflow *workflows.WorkflowTemplate, options *protocols.ExecutorOptions, loader model.WorkflowLoader) error {\n\tshouldNotValidate := false\n\n\tif workflow.Template == \"\" && workflow.Tags.IsEmpty() {\n\t\treturn errors.New(\"invalid workflow with no templates or tags\")\n\t}\n\tif len(workflow.Subtemplates) > 0 || len(workflow.Matchers) > 0 {\n\t\tshouldNotValidate = true\n\t}\n\tif err := parseWorkflowTemplate(workflow, preprocessor, options, loader, shouldNotValidate); err != nil {\n\t\treturn err\n\t}\n\tfor _, subtemplates := range workflow.Subtemplates {\n\t\tif err := parseWorkflow(preprocessor, subtemplates, options, loader); err != nil {\n\t\t\tgologger.Warning().Msgf(\"Could not parse workflow: %v\\n\", err)\n\t\t\tcontinue\n\t\t}\n\t}\n\tfor _, matcher := range workflow.Matchers {\n\t\tif len(matcher.Name.ToSlice()) > 0 {\n\t\t\tif err := matcher.Compile(); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"could not compile workflow matcher\")\n\t\t\t}","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/templates/workflows.go#L11-L47","documentation":"parseWorkflow (pkg/templates/workflows.go:29) requires every node of a `workflows:` definition to carry either a `template:` path or a non-empty `tags:` list; with both empty the node cannot resolve to any template and the error is returned. Subtemplates are parsed recursively by the same function, so nested entries must satisfy the same rule. Callers only log a warning ('Could not parse workflow ...') and skip the file/entry, so the scan proceeds without those templates rather than aborting.","triggerScenarios":"A workflow YAML whose `workflows:` entry or nested `subtemplates:` entry has neither `template:` nor `tags:`; indentation errors that detach subtemplates from their parent, leaving an effectively empty node; tags given as an empty list.","commonSituations":"Hand-written workflows missing the template line; copy-paste from docs that drops one line; YAML reformatting that shifts indentation of subtemplates/matchers.","solutions":["Add either `template: path/to/template.yaml` or `tags: ['some','tags']` to the offending entry","Fix indentation so every subtemplate sits under a parent that itself has template or tags","Run `nuclei -validate` against the workflow to pinpoint the file and entry","Confirm tags is a real YAML list, not an empty scalar"],"exampleFix":"# before\nworkflows:\n  - subtemplates:\n      - tags: rce\n\n# after\nworkflows:\n  - template: cves/2021/CVE-2021-xxx.yaml\n    subtemplates:\n      - tags: rce","handlingStrategy":"validation","validationCode":"// before running a workflow, assert every node resolves\nfunc workflowNodesValid(wfs []workflows.WorkflowTemplate) error {\n    for _, w := range wfs {\n        if w.Template == \"\" && w.Tags.IsEmpty() {\n            return fmt.Errorf(\"workflow node needs template or tags\")\n        }\n        if err := workflowNodesValid(w.Subtemplates); err != nil {\n            return err\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run nuclei -validate on workflow files before scans","Lint that every workflows: entry has template: or a non-empty tags: list","Keep subtemplates indented directly under their parent entry"],"tags":["go","nuclei","yaml","workflows","templates","validation"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}