crowdsecurity/crowdsec · error

could not parse journalctl DSN: %w

Error message

could not parse journalctl DSN: %w

What it means

After stripping the 'journalctl://' prefix, the remainder is parsed as a URL query string with url.ParseQuery. If that remainder contains malformed percent-encoding, an invalid escape, or a stray semicolon, ParseQuery fails and the error is wrapped with this message.

Source

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

	var (
		filters  []string
		since    string
		logLevel log.Level
	)

	// format for the DSN is : journalctl://filters=FILTER1&filters=FILTER2
	if !strings.HasPrefix(dsn, "journalctl://") {
		return fmt.Errorf("invalid DSN %s for journalctl source, must start with journalctl://", dsn)
	}

	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":

View on GitHub (pinned to 909b515798)

Solutions

  1. URL-encode the query values: replace spaces with %20, '%' with %25, '&' with %26.
  2. Inspect the wrapped inner error ('invalid URL escape ...') to locate the exact bad character.
  3. Keep filters to values without reserved query characters, or pre-encode them with url.QueryEscape.
  4. Remove stray semicolons or unmatched '=' from the DSN.

Example fix

// before
s.ConfigureByDSN("journalctl://filters=_SYSTEMD_UNIT=sshd.service&_SYSTEMD_UNIT=100%")
// after
s.ConfigureByDSN("journalctl://filters=_SYSTEMD_UNIT=sshd.service&filters=_SYSTEMD_UNIT=100%25")
Defensive patterns

Strategy: validation

Validate before calling

qs := strings.TrimPrefix(dsn, "journalctl://")
if _, err := url.ParseQuery(qs); err != nil {
    return fmt.Errorf("bad query part %q: %w", qs, err)
}

Try / catch

if err := src.ConfigureByDSN(dsn); err != nil {
    var pe *url.Error
    if errors.As(err, &pe) { /* percent-encoding issue */ }
}

Prevention

When it happens

Trigger: Calling ConfigureByDSN with a DSN whose query part is malformed, e.g. 'journalctl://filters=%ZZ' (bad percent-escape) or 'journalctl://filters=a;b=1'.

Common situations: Filters containing characters that must be URL-encoded (&, =, %) pasted raw; shell variables expanding unexpectedly inside the DSN; truncated DSN strings.

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/3229ae9edbab0caf. Report an issue: GitHub.