crowdsecurity/crowdsec · error
unable to parse yaml file
Error message
unable to parse yaml file %s : %w
What it means
After reading the appsec config file, LoadByPath unmarshals it into a temporary AppsecConfig with yaml.UnmarshalStrict. Strict mode rejects unknown keys, so this error fires both for syntactically invalid YAML and for config keys that do not exist on the struct. The wrapped yaml error names the exact line and offending key.
Solutions
- Read the wrapped yaml error line/column and fix the YAML syntax or the unknown key at that line
- Compare your keys against the documented AppsecConfig fields for your CrowdSec version
- Replace tabs with spaces and validate indentation with a YAML linter
- Pin configs to keys supported by your installed version when copying examples from newer docs
Example fix
// before on_sucess: break // after on_success: break
Defensive patterns
Strategy: validation
Prevention
- Strict-lint YAML in CI
- No tabs; copy documented keys only
When it happens
Trigger: LoadByPath on a YAML file with syntax errors (bad indentation, tabs, unclosed quotes); a typo'd or unknown top-level key (strict unmarshaling); a value of the wrong type for a known field.
Common situations: Hand-edited appsec-config with a misspelled option like 'on_sucess' instead of 'on_success'; tabs instead of spaces; mixing appsec-config keys into a rules file loaded as appsec config; config from an older/newer CrowdSec version using removed keys.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- appsec rule name is empty for
- cannot compile variable regexp
- cannot parse FileAcquisition configuration
- cannot parse
- cannot parse S3Acquisition configuration
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/071c9e2ee313d4ec.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/appsec/appsec.go:673
/* wc.Name is actually the datasource name.*/
wc.Logger = wc.Logger.Dup().WithField("name", wc.Name)
wc.Logger.Logger.SetLevel(*wc.LogLevel)
}
func (wc *AppsecConfig) LoadByPath(file string) error {
wc.Logger.Debugf("loading config %s", file)
yamlFile, err := os.ReadFile(file)
if err != nil {
return fmt.Errorf("unable to read file %s : %w", file, err)
}
// as LoadByPath can be called several time, we append rules/hooks, but override other options
var tmp AppsecConfig
err = yaml.UnmarshalStrict(yamlFile, &tmp)
if err != nil {
return fmt.Errorf("unable to parse yaml file %s : %w", file, err)
}
// Normalize phase-scoped sections: merge rules, options, and variables_tracking
// into flat fields. Hooks stay in the phase sections for Build() to compile separately.
tmp.normalizePhaseScoped()
if wc.Name == "" && tmp.Name != "" {
wc.Name = tmp.Name
}
// We can append rules/hooks
if tmp.OutOfBandRules != nil {
wc.OutOfBandRules = append(wc.OutOfBandRules, tmp.OutOfBandRules...)
}
if tmp.InBandRules != nil {
wc.InBandRules = append(wc.InBandRules, tmp.InBandRules...)
}View on GitHub (pinned to 909b515798)