{"record":{"id":"7a7191bad64dc3ea","repo":"crowdsecurity/crowdsec","slug":"failed-to-parse-s-w","errorCode":null,"errorMessage":"failed to parse %s: %w","messagePattern":"failed to parse (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/cwhub/sync.go","lineNumber":202,"sourceCode":"\t\tFileName: fileName,\n\t\tState: ItemState{\n\t\t\tLocalPath: path,\n\t\t\tlocal:     true,\n\t\t\tUpToDate:  true,\n\t\t},\n\t}\n\n\t// try to read the name from the file\n\titemName := localItemName{}\n\n\titemContent, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read %s: %w\", path, err)\n\t}\n\n\terr = yaml.Unmarshal(itemContent, &itemName)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse %s: %w\", path, err)\n\t}\n\n\tif itemName.Name != \"\" {\n\t\titem.Name = itemName.Name\n\t}\n\n\treturn item, nil\n}\n\n// ErrSkipPath is a sentinel to skip regular files because \"nil, nil\" is ambiguous. Returning SkipDir with files would skip the rest of the directory.\nvar ErrSkipPath = errors.New(\"sentinel\")\n\nfunc (h *Hub) itemVisit(path string, f os.DirEntry, err error) (*itemSpec, error) {\n\tif err != nil {\n\t\th.logger.Debugf(\"while syncing hub dir: %s\", err)\n\t\t// there is a path error, we ignore the file\n\t\treturn nil, ErrSkipPath\n\t}","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/cwhub/sync.go#L184-L220","documentation":"After reading a local item file, newLocalItem unmarshals it as yaml into localItemName to pick up an optional 'name' key. If the file content is not valid yaml (or the top-level structure isn't a mapping), yaml.Unmarshal fails and the error is wrapped in 'failed to parse %s'. The item is skipped/aborted for that file.","triggerScenarios":"A yaml file in the scanned config directory contains syntax errors: tabs instead of spaces, unclosed quotes, duplicate keys rejected by the parser, or non-mapping content like a bare string or a binary file with a .yaml extension.","commonSituations":"Hand-edited config files with indentation mistakes; files renamed to .yaml that aren't yaml (e.g. copied logs, editor swap files); copy/paste of yaml with smart quotes or tabs.","solutions":["Validate the file with a yaml linter/parser: `python3 -c 'import yaml,sys; yaml.safe_load(open(sys.argv[1]))' <file>`","Fix the syntax error reported at the line indicated in the wrapped message (tabs, indentation, quotes)","Remove or rename non-yaml files that end in .yaml out of the config directory","If it's a hub item, reinstall it with cscli to restore pristine content"],"exampleFix":"// before: config/scenarios/my.yaml\nname:\tcrowdsecurity/my\t# tab indentation, parse fails\n// after\nname: crowdsecurity/my  # spaces only","handlingStrategy":"validation","validationCode":"import (\n\t\"os\"\n\t\"gopkg.in/yaml.v3\"\n)\n\nfunc validYAML(path string) error {\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar m map[string]any\n\treturn yaml.Unmarshal(b, &m)\n}\n// call for each .yaml in the config dir before starting crowdsec","typeGuard":null,"tryCatchPattern":"if err := hub.Load(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"failed to parse\") {\n\t\tvar yamlErr *yaml.TypeError\n\t\tlog.Warnf(\"bad yaml in config dir: %v\", err)\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Validate every yaml with a linter (yamllint) before committing it to the config dir","Use spaces, never tabs, in yaml files","Don't rename non-yaml files to .yaml; keep editor swap/backup files out of the config directory"],"tags":["yaml","parsing","config","crowdsec"],"backgroundTag":"yaml-parse-error","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"}