crowdsecurity/crowdsec · error

failed to parse feature flags: %w

Error message

failed to parse feature flags: %w

What it means

SetFromYaml parses a feature-flags YAML document and applies it. If yaml.Unmarshal fails with anything other than io.EOF (EOF means an empty file, which is tolerated as 'no feature flags'), the parse error is wrapped and returned. It indicates the config file contains invalid YAML.

Source

Thrown at pkg/fflag/features.go:203

		logger.Debugf("Feature flag: %s=%t (from envvar). %s", featureName, enable, feat.Description)
	}

	return nil
}

func (fr *FeatureRegister) SetFromYaml(r io.Reader, logger *logrus.Logger) error {
	var cfg []string

	bys, err := io.ReadAll(r)
	if err != nil {
		return err
	}

	// parse config file
	if err := yaml.Unmarshal(bys, &cfg); err != nil {
		if !errors.Is(err, io.EOF) {
			return fmt.Errorf("failed to parse feature flags: %w", err)
		}

		logger.Debug("No feature flags in config file")
	}

	// set features
	for _, k := range cfg {
		feat, err := fr.GetFeature(k)
		if err != nil {
			logger.Errorf("Ignored feature flag '%s': %s", k, err)
			continue
		}

		err = feat.Set(true)

		switch {
		case errors.Is(err, ErrFeatureRetired):
			logger.Errorf("Ignored feature flag '%s': %s. %s", k, err, feat.DeprecationMsg)

View on GitHub (pinned to 909b515798)

Solutions

  1. Fix the YAML syntax error reported by the wrapped message (line/column are usually included)
  2. Replace tabs with spaces and check indentation of nested keys
  3. Ensure the file's features section is a map of flag-name to enabled/config value
  4. Validate the file with a YAML linter or `cscli` startup before deploying

Example fix

// bad YAML
features:
		my-flag: true   # tabs, wrong indent
// good YAML
features:
  my-flag: true
Defensive patterns

Strategy: validation

Validate before calling

bys, _ := io.ReadAll(r)
if err := yaml.Unmarshal(bys, &map[string]any{}); err != nil && !errors.Is(err, io.EOF) {
    return fmt.Errorf("invalid feature flags YAML: %w", err)
}

Try / catch

if err := fr.SetFromYaml(f, logger); err != nil {
    if strings.HasPrefix(err.Error(), "failed to parse feature flags") {
        // keep previous config, surface the YAML error to the operator
        logger.Errorf("fix feature_flags.yaml: %v", err)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Calling SetFromYaml(reader, logger) (directly or via SetFromYamlFile) with a reader containing syntactically invalid YAML — bad indentation, tabs, wrong types for known fields, stray characters.

Common situations: Hand-edited feature flag config files; tabs instead of spaces; features section not a map; a value that doesn't unmarshal into the expected field type.

Understand the failure class

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/deffa560f72dd53d. Report an issue: GitHub.