crowdsecurity/crowdsec · error

failed to parse DSN

Error message

failed to parse DSN %s: %w

What it means

ConfigureByDSN parses the acquisition DSN string with url.Parse before interpreting it as a docker source. If url.Parse returns an error (malformed URL syntax), the DSN string is included and the underlying error wrapped with this prefix.

Solutions

  1. Inspect the DSN string for illegal URL characters and remove/escape them (use %XX encoding).
  2. Ensure percent-encodings are valid hex (e.g. %20 not %zz).
  3. Simplify the DSN to a known-good form: docker://<container>?<params>.

Example fix

// before
log_path: 'docker://mycontainer?log_level=100%'
// after
log_path: 'docker://mycontainer?log_level=info'
Defensive patterns

Strategy: validation

Validate before calling

if _, err := url.Parse(dsn); err != nil {
    return fmt.Errorf("malformed docker DSN %q: %w", dsn, err)
}

Prevention

When it happens

Trigger: ConfigureByDSN called with a dsn string that url.Parse rejects — e.g. stray control characters, invalid percent-encoding (`%zz`), or malformed IPv6 literal brackets.

Common situations: A docker:// DSN with an accidentally pasted newline or space; unescaped `%` in a query parameter; corrupted acquis.yaml entry with broken quoting.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at pkg/acquisition/modules/docker/config.go:202

		if !hasServiceConfig {
			// we set to false cause user didnt provide service configuration even though we are a swarm manager
			d.isSwarmManager = false
			d.logger.Warn("node is swarm manager, but no service configuration provided - service monitoring will be disabled, if this is unintentional please apply constraints")
		}
	}

	d.backoffFactory = newDockerBackOffFactory()

	return nil
}

func (d *Source) ConfigureByDSN(_ context.Context, dsn string, labels map[string]string, logger *log.Entry, uuid string) error {
	var err error

	parsedURL, err := url.Parse(dsn)
	if err != nil {
		return fmt.Errorf("failed to parse DSN %s: %w", dsn, err)
	}

	if parsedURL.Scheme != d.GetName() {
		return fmt.Errorf("invalid DSN %s for docker source, must start with %s://", dsn, d.GetName())
	}

	d.Config = Configuration{
		FollowStdout: true,
		FollowStdErr: true,
	}
	d.Config.UniqueId = uuid
	d.Config.ContainerName = make([]string, 0)
	d.Config.ContainerID = make([]string, 0)
	d.runningContainerState = tracker.NewTracker[*ContainerConfig]()
	d.runningServiceState = tracker.NewTracker[*ContainerConfig]()
	d.Config.Mode = configuration.CAT_MODE
	d.logger = logger
	d.Config.Labels = labels

View on GitHub (pinned to 909b515798)