crowdsecurity/crowdsec · error

expected exactly one value for 'log_level'

Error message

expected exactly one value for 'log_level'

What it means

In ConfigureByDSN, the log_level query parameter must be supplied exactly once because the code needs a single log.Level value. Passing it multiple times (a slice with len != 1) is ambiguous and rejected in pkg/acquisition/modules/journalctl/config.go:105 before log.ParseLevel is attempted.

Source

Thrown at pkg/acquisition/modules/journalctl/config.go:105

	}

	qs := strings.TrimPrefix(dsn, "journalctl://")
	if qs == "" {
		return errors.New("empty journalctl:// DSN")
	}

	params, err := url.ParseQuery(qs)
	if err != nil {
		return fmt.Errorf("could not parse journalctl DSN: %w", err)
	}

	for key, value := range params {
		switch key {
		case "filters":
			filters = append(filters, value...)
		case "log_level":
			if len(value) != 1 {
				return errors.New("expected exactly one value for 'log_level'")
			}

			lvl, err := log.ParseLevel(value[0])
			if err != nil {
				return err
			}

			logLevel = lvl
		case "since":
			if len(value) != 1 {
				return errors.New("expected exactly one value for 'since'")
			}

			since = value[0]
		default:
			return fmt.Errorf("unsupported key %s in journalctl DSN", key)
		}
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Provide log_level exactly once in the DSN: journalctl://?filters=...&log_level=info.
  2. Deduplicate parameters before building the DSN (keep the last/intended value).
  3. If multiple levels were intended, note journalctl DSNs accept a single log_level; move filtering to the filters parameter.

Example fix

// before
journalctl://?filters=_SYSTEMD_UNIT=ssh&log_level=info&log_level=debug

// after
journalctl://?filters=_SYSTEMD_UNIT=ssh&log_level=info
Defensive patterns

Strategy: validation

Validate before calling

params := urlVals["log_level"]
if len(params) != 1 {
    return fmt.Errorf("log_level must appear exactly once, got %d", len(params))
}
if _, err := log.ParseLevel(params[0]); err != nil {
    return err
}

Type guard

func singleValue(vals url.Values, key string) (string, bool) {
    v := vals[key]
    if len(v) != 1 { return "", false }
    return v[0], true
}

Try / catch

if err := src.ConfigureByDSN(ctx, dsn); err != nil {
    if strings.Contains(err.Error(), "log_level") {
        // rebuild DSN with a single log_level value
    }
}

Prevention

When it happens

Trigger: Calling ConfigureByDSN with a DSN containing log_level more than once, e.g. journalctl://?filters=x&log_level=info&log_level=debug.

Common situations: Query builders that append a parameter per value (array semantics) when the consumer expects a scalar; accidental duplication from merging DSN strings; shell loop appending the flag repeatedly.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


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