{"record":{"id":"a12906576e24bcb4","repo":"crowdsecurity/crowdsec","slug":"s-s-has-no-stage","errorCode":null,"errorMessage":"%s:%s has no stage","messagePattern":"(.+?):(.+?) has no stage","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/cwhub/hub.go","lineNumber":94,"sourceCode":"\n\tif err := json.Unmarshal(bidx, &h.items); err != nil {\n\t\treturn fmt.Errorf(\"failed to parse index: %w\", err)\n\t}\n\n\t// Iterate over the different types to complete the struct\n\tfor _, itemType := range ItemTypes {\n\t\tfor name, item := range h.GetItemMap(itemType) {\n\t\t\tif item == nil {\n\t\t\t\t// likely defined as empty object or null in the index file\n\t\t\t\treturn fmt.Errorf(\"%s:%s has no index metadata\", itemType, name)\n\t\t\t}\n\n\t\t\tif item.RemotePath == \"\" {\n\t\t\t\treturn fmt.Errorf(\"%s:%s has no download path\", itemType, name)\n\t\t\t}\n\n\t\t\tif (itemType == PARSERS || itemType == POSTOVERFLOWS) && item.Stage == \"\" {\n\t\t\t\treturn fmt.Errorf(\"%s:%s has no stage\", itemType, name)\n\t\t\t}\n\n\t\t\titem.hub = h\n\t\t\titem.Name = name\n\n\t\t\titem.Type = itemType\n\t\t\titem.FileName = path.Base(item.RemotePath)\n\n\t\t\titem.logMissingSubItems()\n\n\t\t\tif item.latestHash() == \"\" {\n\t\t\t\th.logger.Errorf(\"invalid hub item %s: latest version missing from index\", item.FQName())\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/cwhub/hub.go#L76-L112","documentation":"parseIndex requires parsers and postoverflows items to declare a Stage (e.g. s00-raw, s01-parse), because these item types are organized by stage directories and loading/execution order depends on it. Entries missing a stage are rejected at hub load time.","triggerScenarios":"Hub.Load()/parseIndex encounters an index entry of type PARSERS or POSTOVERFLOWS whose Stage field is empty — usually a manually written index entry or an index generated by a version that didn't record stages.","commonSituations":"Adding a custom parser entry to .index.json by hand without a stage key; migrating an old hub index; scripted index generation that omits optional fields.","solutions":["Set the `stage` field on the index entry (e.g. \"s01-parse\")","Re-run `cscli hub update` to regenerate the index","Move the parser file into a properly staged directory and reinstall via `cscli hub`","Only collections/parsers/postoverflows need stages — verify the item's type is correct"],"exampleFix":"// before\n\"crowdsecurity/my-parser\": {\"type\":\"parsers\",\"remote_path\":\"parsers/crowdsecurity/my-parser.yaml\"}\n// after\n\"crowdsecurity/my-parser\": {\"type\":\"parsers\",\"stage\":\"s02-enrich\",\"remote_path\":\"parsers/s02-enrich/crowdsecurity/my-parser.yaml\"}","handlingStrategy":"validation","validationCode":"if (itemType == cwhub.PARSERS || itemType == cwhub.POSTOVERFLOWS) && item.Stage == \"\" {\n    return fmt.Errorf(\"%s:%s needs a stage\", itemType, name)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include stage in parser/postoverflow index entries","Generate index entries programmatically from directory layout","Verify custom parsers install under a staged directory"],"tags":["hub","index","parser"],"backgroundTag":"missing-required-config-field","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}