crowdsecurity/crowdsec · error

journalctl exited with error: %w

Error message

journalctl exited with error: %w

What it means

After journalctl exits, runJournalCtl checks whether the parent context was canceled (normal shutdown, in which case 'signal: killed' is ignored and nil is returned). If the context was not canceled and the command exited non-zero, the exit error is wrapped with this message — meaning journalctl itself failed (bad args, no permission to read the journal, corrupted journal, etc.).

Source

Thrown at pkg/acquisition/modules/journalctl/run.go:126

			}
		}

		return nil
	})

	cleanup := func() error {
		// drain scanners
		_ = g.Wait()
		// reap journalctl, check status code
		cmdErr := cmd.Wait()

		// if the parent context was canceled, the journalctl error is likely "signal: killed" and we ignore that
		if ctx.Err() != nil {
			return nil //nolint:nilerr
		}

		if cmdErr != nil {
			return fmt.Errorf("journalctl exited with error: %w", cmdErr)
		}

		// clean journalctl exit: should only happen in oneshot
		return nil
	}

	for {
		select {
		case <-ctx.Done():
			s.logger.Info("Datasource stopping")
			return cleanup()
		case stdoutLine, ok := <-stdoutChan:
			if !ok {
				s.logger.Debug("stdout channel is closed, stopping datasource")
				return cleanup()
			}

			line := pipeline.Line{

View on GitHub (pinned to 909b515798)

Solutions

  1. Run the same journalctl command manually (journalctl --output=json with your filters) to see its real error output.
  2. Add the crowdsec user to the systemd-journal (or adm) group: usermod -aG systemd-journal crowdsec.
  3. Fix invalid filter expressions — journalctl rejects unknown journal fields with a non-zero exit.
  4. Check journalctl binary presence/version: which journalctl; journalctl --version.
  5. If the error says 'signal: killed' during shutdown, it is benign — context cancellation handling already ignores that case.

Example fix

// before (as unprivileged user)
s.Stream() // journalctl exits 1: permission denied
// after
// systemctl restart crowdsec  (after adding user to systemd-journal group)
s.Stream()
Defensive patterns

Strategy: try-catch

Validate before calling

// before enabling the source, verify the exact command works
out, err := exec.Command("journalctl", append([]string{"--output=json"}, args...)...).CombinedOutput()
if err != nil { return fmt.Errorf("journalctl precheck failed: %v: %s", err, out) }

Try / catch

if err := src.Stream(); err != nil {
    if strings.Contains(err.Error(), "journalctl exited with error") {
        // run journalctl manually with same args; fix perms/filters
    }
}

Prevention

When it happens

Trigger: OneShot or Stream runs journalctl which terminates with a non-zero exit code while crowdsec is not shutting down — e.g. invalid filters, user not in systemd-journal/adm group, or journald unavailable.

Common situations: Running crowdsec as a user lacking journal read permissions; typo in a filter causing journalctl to exit with 'unknown field'; system journal corruption; journalctl removed/upgraded mid-run.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


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