{"record":{"id":"959561b035cd6820","repo":"crowdsecurity/crowdsec","slug":"empty-journalctl-dsn","errorCode":null,"errorMessage":"empty journalctl:// DSN","messagePattern":"empty journalctl:// DSN","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/journalctl/config.go","lineNumber":91,"sourceCode":"\ts.metricsLevel = metricsLevel\n\treturn nil\n}\n\nfunc (s *Source) ConfigureByDSN(_ context.Context, dsn string, labels map[string]string, logger *log.Entry, uuid string) error {\n\tvar (\n\t\tfilters  []string\n\t\tsince    string\n\t\tlogLevel log.Level\n\t)\n\n\t// format for the DSN is : journalctl://filters=FILTER1&filters=FILTER2\n\tif !strings.HasPrefix(dsn, \"journalctl://\") {\n\t\treturn fmt.Errorf(\"invalid DSN %s for journalctl source, must start with journalctl://\", dsn)\n\t}\n\n\tqs := strings.TrimPrefix(dsn, \"journalctl://\")\n\tif qs == \"\" {\n\t\treturn errors.New(\"empty journalctl:// DSN\")\n\t}\n\n\tparams, err := url.ParseQuery(qs)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not parse journalctl DSN: %w\", err)\n\t}\n\n\tfor key, value := range params {\n\t\tswitch key {\n\t\tcase \"filters\":\n\t\t\tfilters = append(filters, value...)\n\t\tcase \"log_level\":\n\t\t\tif len(value) != 1 {\n\t\t\t\treturn errors.New(\"expected exactly one value for 'log_level'\")\n\t\t\t}\n\n\t\t\tlvl, err := log.ParseLevel(value[0])\n\t\t\tif err != nil {","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/journalctl/config.go#L73-L109","documentation":"ConfigureByDSN accepts DSNs of the form journalctl://<query-string>. After stripping the prefix, an empty remainder means there are no parameters at all — in particular no filters — so the source would be unusable and the call fails in pkg/acquisition/modules/journalctl/config.go:91.","triggerScenarios":"Calling ConfigureByDSN(ctx, \"journalctl://\") with no query string, or building the DSN from variables that are all empty.","commonSituations":"Template/CLI assembly that drops the query string; truncation of the DSN at the '?' by another tool; copy-paste that lost the parameters.","solutions":["Append query parameters, at minimum filters: journalctl://?filters=_SYSTEMD_UNIT=ssh.service.","If configuring via YAML instead, use an acquis.yaml entry with journal_filter rather than a bare DSN.","Debug DSN generation code to ensure the query string is not dropped or truncated."],"exampleFix":"// before\ncrowdsec -type syslog -dsn 'journalctl://'\n\n// after\ncrowdsec -type syslog -dsn 'journalctl://?filters=_SYSTEMD_UNIT=ssh.service&log_level=info'","handlingStrategy":"validation","validationCode":"qs := strings.TrimPrefix(dsn, \"journalctl://\")\nif qs == \"\" {\n    return errors.New(\"journalctl DSN needs at least a filters parameter\")\n}","typeGuard":"func validJournalctlDSN(dsn string) bool {\n    q, ok := strings.CutPrefix(dsn, \"journalctl://\")\n    return ok && q != \"\"\n}","tryCatchPattern":"if err := src.ConfigureByDSN(ctx, dsn); err != nil {\n    if strings.Contains(err.Error(), \"empty journalctl:// DSN\") {\n        // append ?filters=... and retry\n    }\n}","preventionTips":["Build DSNs with url.Values encoding rather than string concatenation.","Assert non-empty query string in code that generates DSNs.","Prefer YAML acquisition config over bare DSNs for complex setups."],"tags":["dsn","journalctl","config"],"backgroundTag":"invalid-url-format","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}