crowdsecurity/crowdsec · error
labels not a map
Error message
labels not a map
What it means
After enabling, the 'labels' entry must be a map[string]any of label key/values to attach to events; the assertion parsedLabels["labels"].(map[string]any) failed, so the entity is rejected. This protects the source from malformed or flat label structures.
Source
Thrown at pkg/acquisition/modules/docker/source.go:108
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")
}
d.logger.Debugf("%s labels %+v", entityType, labelsTypeCast)
labels := make(map[string]string)
for k, v := range labelsTypeCast {
if v, ok := v.(string); ok {
log.Debugf("label %s is a string with value %s", k, v)
labels[k] = v
continue
}
d.logger.Errorf("label %s is not a string", k)
}
return labels, nil
}View on GitHub (pinned to 909b515798)
Solutions
- Express labels as key/value pairs under crowdsec.labels, e.g. crowdsec.labels.type=syslog and crowdsec.labels.program=ssh
- Never assign a scalar to crowdsec.labels itself — it must be a map
- If using compose, structure it as labels: { crowdsec: { enable: 'true', labels: { type: syslog } } } and verify nesting
- Dump the effective labels with 'docker inspect --format "{{json .Config.Labels}}"' to confirm the structure
Example fix
# before (scalar where a map is required) labels: - crowdsec.enable=true - crowdsec.labels=syslog # after (map of label key/values) labels: - crowdsec.enable=true - crowdsec.labels.type=syslog - crowdsec.labels.program=sshd
Defensive patterns
Strategy: type-guard
Validate before calling
if strings.EqualFold(labels["crowdsec.enable"], "true") {
for k, v := range labels {
if strings.HasPrefix(k, "crowdsec.labels.") {
_ = k + v // flat per-key labels are fine; a scalar crowdsec.labels is not
}
}
} Type guard
func labelsIsMap(v any) bool {
_, ok := v.(map[string]any)
return ok
} Try / catch
if _, err := source.EvalContainer(ctx, ctr); err != nil {
if err.Error() == "labels not a map" {
log.Errorf("container %s: crowdsec.labels must be key/value pairs, not a scalar", ctr.ID)
}
} Prevention
- Never give crowdsec.labels a scalar value; use crowdsec.labels.<key>=<value> entries
- Inspect effective labels with docker inspect to confirm structure before debugging
- Keep compose label nesting explicit and lint for maps under crowdsec.labels
When it happens
Trigger: processCrowdsecLabels (via EvalContainer/EvalService) receives parsedLabels["labels"] as a non-map value — e.g. a string like crowdsec.labels=syslog, a list, or a bool — instead of a map of key/value pairs.
Common situations: User wrote crowdsec.labels as a single flat label with a scalar value instead of per-key labels (crowdsec.labels.type=...); a list under labels in YAML; tooling that flattens nested labels into one string.
Related errors
- crowdsec.enable not a string
- 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/6420d1edd4b53051.
Report an issue: GitHub.