crowdsecurity/crowdsec · error
cannote create %s reader: %w
Error message
cannote create %s reader: %w
What it means
Wraps any failure from Configuration.NewReader() while the kafka acquisition source is configured. NewReader can fail when both group_id and partition are set (mutually exclusive), or when kafka.ReaderConfig.Validate() rejects the combination. Note the typo 'cannote' in the message itself — searching logs for 'cannot create kafka reader' will miss it.
Source
Thrown at pkg/acquisition/modules/kafka/config.go:90
func (s *Source) Configure(_ context.Context, yamlConfig []byte, logger *log.Entry, metricsLevel metrics.AcquisitionMetricsLevel) error {
s.logger = logger
s.metricsLevel = metricsLevel
s.logger.Debugf("start configuring %s source", s.GetName())
err := s.UnmarshalConfig(yamlConfig)
if err != nil {
return err
}
dialer, err := s.Config.NewDialer()
if err != nil {
return fmt.Errorf("cannot create %s dialer: %w", s.GetName(), err)
}
s.Reader, err = s.Config.NewReader(dialer, s.logger)
if err != nil {
return fmt.Errorf("cannote create %s reader: %w", s.GetName(), err)
}
if s.Reader == nil {
return fmt.Errorf("cannot create %s reader", s.GetName())
}
s.logger.Debugf("successfully configured %s source", s.GetName())
return nil
}
func (c *Configuration) NewTLSConfig() (*tls.Config, error) {
tlsConfig := tls.Config{
InsecureSkipVerify: c.TLS.InsecureSkipVerify,
}
cert, err := tls.LoadX509KeyPair(c.TLS.ClientCert, c.TLS.ClientKey)
if err != nil {View on GitHub (pinned to 909b515798)
Solutions
- In the kafka acquisition yaml, keep only one of `group_id` or `partition` — they are mutually exclusive
- Remove the `partition:` key if you intend consumer-group semantics; partition mode also only reads a single partition
- Check the wrapped %w error in logs: 'cannot specify both group_id and partition' vs a Validate() message
- Read the yaml with strict parsing (CrowdSec already does) to confirm no unexpected keys cause a mis-parse
Example fix
// before source: kafka brokers: [broker:9092] topic: crowdsec group_id: crowdsec partition: 1 # mutually exclusive // after source: kafka brokers: [broker:9092] topic: crowdsec group_id: crowdsec
Defensive patterns
Strategy: validation
Validate before calling
if cfg.GroupID != "" && cfg.Partition != 0 {
return errors.New("kafka: group_id and partition are mutually exclusive")
} Try / catch
if err := src.Configure(ctx, yamlCfg, logger, lvl); err != nil {
if strings.Contains(err.Error(), "both group_id and partition") {
logger.Error("fix acquisition yaml: drop either group_id or partition")
}
return err
} Prevention
- Pick consumption mode (group_id OR partition) up front and keep only that key
- Grep your acquis yaml for both keys when upgrading configs
- Remember partition 0 is the zero-value, so `partition: 0` silently means 'no partition'
When it happens
Trigger: Configure() calls Config.NewReader(dialer, logger) and it returns an error — specifically when a kafka acquisition yaml sets both `group_id` and a non-zero `partition`, or when kafka-go's ReaderConfig.Validate() fails (e.g. invalid Address/Group balancing config).
Common situations: Operator converts from partition-based to consumer-group consumption and forgets to remove `partition:`; kafka-go version where Validate() rejects some combination; copy-pasted config keeping a stale `partition: 1`.
Related errors
- cannot create %s dialer: %w
- path must start with /
- cannot specify both group_id and partition
- on_challenge hooks are only valid in-band, not under outofba
- empty cti key
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/cde47ff1c9ae1c96.
Report an issue: GitHub.