crowdsecurity/crowdsec · error
crowdsec.enable not a string
Error message
crowdsec.enable not a string
What it means
Docker labels are always strings, but processCrowdsecLabels received a parsed 'enable' entry whose dynamic value is not a string, so the type assertion parsedLabels["enable"].(string) failed and the entity is rejected. This guard exists because labels may be re-parsed/normalized before validation.
Source
Thrown at pkg/acquisition/modules/docker/source.go:92
return parseLabels(containerDetails.Container.Config.Labels)
}
func (d *Source) processCrowdsecLabels(parsedLabels map[string]any, entityID string, entityType string) (map[string]string, error) {
if len(parsedLabels) == 0 {
d.logger.Tracef("%s has no 'crowdsec' labels set, ignoring %s: %s", entityType, entityType, entityID)
return nil, errors.New("no crowdsec labels")
}
if _, ok := parsedLabels["enable"]; !ok {
d.logger.Errorf("%s has 'crowdsec' labels set but no 'crowdsec.enable' key found", entityType)
return nil, errors.New("no crowdsec.enable key")
}
enable, ok := parsedLabels["enable"].(string)
if !ok {
d.logger.Errorf("%s has 'crowdsec.enable' label set but it's not a string", entityType)
return nil, errors.New("crowdsec.enable not a string")
}
if strings.ToLower(enable) != "true" {
d.logger.Debugf("%s has 'crowdsec.enable' label not set to true ignoring %s: %s", entityType, entityType, entityID)
return nil, errors.New("crowdsec.enable not true")
}
if _, ok = parsedLabels["labels"]; !ok {
d.logger.Errorf("%s has 'crowdsec.enable' label set to true but no 'labels' keys found", entityType)
return nil, errors.New("no labels key")
}
labelsTypeCast, ok := parsedLabels["labels"].(map[string]any)
if !ok {
d.logger.Errorf("%s has 'crowdsec.enable' label set to true but 'labels' is not a map", entityType)
return nil, errors.New("labels not a map")
}
View on GitHub (pinned to 909b515798)
Solutions
- Set the label as a plain string: crowdsec.enable=true (docker labels are strings; avoid structured config wrappers that coerce types)
- If using a custom label source, ensure values are serialized as strings before reaching the docker source
- Check for tooling or templates that emit YAML booleans and force quoting: crowdsec.enable: "true"
- Pin/verify crowdsec version; older parsers handled label types differently
Example fix
# before (values coerced to bool) labels: crowdsec.enable: true # after (string, as docker labels require) labels: crowdsec.enable: "true"
Defensive patterns
Strategy: type-guard
Validate before calling
v, ok := labels["crowdsec.enable"]
if !ok || reflect.TypeOf(v) != reflect.TypeOf("") {
return fmt.Errorf("crowdsec.enable must be a string, got %T", v)
} Type guard
func enableIsString(v any) bool {
_, ok := v.(string)
return ok
} Try / catch
if _, err := source.EvalContainer(ctx, ctr); err != nil {
if strings.Contains(err.Error(), "crowdsec.enable not a string") {
log.Errorf("container %s: quote the enable label value", ctr.ID)
}
} Prevention
- Quote label values in YAML templates so they stay strings
- Avoid middleware that coerces label values to bool/number
- Test with plain docker labels where values are always strings
When it happens
Trigger: processCrowdsecLabels (via EvalContainer/EvalService) sees parsedLabels["enable"] present but holding a non-string value (e.g. bool or number after custom parsing), failing the .(string) assertion.
Common situations: Users writing enable=true in a config layer that parses YAML/JSON types instead of raw docker labels; custom wrappers feeding non-string label maps; boolean-like values coerced upstream.
Related errors
- labels not a map
- no crowdsec.enable key
- crowdsec.enable not true
- no labels key
- AverageInterval expects a slice of times
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/7927699f7dfd341f.
Report an issue: GitHub.