journalctl: "No journal files were found"

journalctl has four ways of telling you it found nothing. Three of them exit 0.

That is the problem. A script that checks the exit code learns nothing, and the four messages have four different causes. Read the message, not the empty screen.

The four messages

What journalctl prints What happened Exit code
No journal files were found. It opened no files, and hit no errors trying 0
No journal files were opened due to insufficient permissions. Every file it found said no non-zero
Hint: You are currently not seeing messages from the system. It opened some files. You are missing the rest 0
-- No entries -- Files opened fine. Your filter matched nothing 0

The third one is the dangerous one. You get output, it looks like output, and it is a fraction of the log.

All four come out of journal_access_check_and_warn() in src/shared/journal-util.c, except -- No entries --, which journalctl prints at the end when it showed zero lines.

“No journal files were found.”

There is no journal on this machine to read. Check where it would be:

ls -d /var/log/journal /run/log/journal 2>/dev/null

Neither exists, or both are empty. Three common reasons.

Storage=none. journald throws every entry away.

grep -r '^Storage=' /etc/systemd/journald.conf /etc/systemd/journald.conf.d/ 2>/dev/null

journald is not running. Minimal images and containers often ship systemd without it, or without systemd at all.

systemctl is-active systemd-journald

You pointed journalctl somewhere empty. --file, -D and --root all make journalctl read a location you chose instead of this machine’s journal. A typo in the path gets you this message, not an error.

Making the journal survive a reboot

Storage=auto is the compiled-in default on most distributions, and auto means persistent if /var/log/journal exists and volatile if it does not. The directory’s existence is the setting. On a host without it, every reboot starts an empty journal and journalctl -b -1 has nothing to show you.

Create it:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

The mkdir is not redundant. systemd’s tmpfiles rule for /var/log/journal is a z entry, and --create only creates f F w d D v p L c b m entries. A z entry gets its ownership, mode and labels fixed and is never created. Run systemd-tmpfiles --create alone on a host without the directory and nothing happens, silently.

“No journal files were opened due to insufficient permissions.”

Every journal file refused you. This is the one that exits non-zero.

journalctl decides you may read the system journal by checking four things in order:

  1. Are you root? Then yes.
  2. Are you in the systemd-journal group? Then yes.
  3. Is any of your groups in the ACL on /run/log/journal — or on /var/log/journal, if the runtime directory does not exist? Then yes.
  4. Otherwise, no.

Step 3 is why adm works on Debian and Ubuntu and wheel works on some RPM distributions. Neither is built in. The distribution sets an ACL, and journalctl reads that ACL to decide. This also means the check looks at /run/log/journal first when it exists, so a host running volatile can answer differently from the same host running persistent.

Add yourself to the group:

sudo usermod -aG systemd-journal "$USER"

Then log out and back in. Group membership is fixed at login. id -nG will show the new group in a fresh session and not in the one you ran usermod from — which is why this fix so often looks like it did not work.

“Hint: You are currently not seeing messages from the system.”

This is a log_notice, and journalctl exits 0.

It means journalctl opened your own user journal and was refused the system’s. You get a real, populated, incomplete log. Nothing marks the gap.

The full text names the groups it would accept:

Hint: You are currently not seeing messages from the system.
      Users in groups 'adm', 'systemd-journal' can see all messages.
      Pass -q to turn off this notice.

The group list is built from the ACL, so it differs by distribution. When systemd finds no ACL at all it falls back to naming systemd-journal alone.

Two things to take from it. First, the fix is the same usermod as above. Second, do not pass -q to make it go away in a script. -q suppresses the hint and keeps the partial output. Suppressing it is how a monitoring script ends up reporting on a tenth of the log for a year.

“– No entries –”

The journal is there and readable. Your filter excluded everything.

journalctl prints this when it showed zero lines, and exits 0 — unless you used -g, which returns non-zero on no match so it behaves like grep in a script.

Four filters that match nothing more often than people expect:

The unit name is wrong. journalctl -u nginx and journalctl -u nginx.service both work, but -u nginx.conf or a typo silently matches nothing. systemctl list-units --type=service --all | grep -i <name> gets the real name. See viewing one service’s logs with journalctl -u.

-p err on an application that logs to stderr. SyslogLevel= defaults to info and applies to stderr exactly as it does to stdout. A service writing errors to stderr still lands in the journal at priority 6, so -p err returns nothing while the log is visibly full of errors. See showing only errors in journalctl.

A bare date in --until. journalctl fills in the parts you omit, and an omitted time is 00:00:00. --until 2026-09-20 stops at midnight starting the 20th, so the whole of the 20th is gone. See viewing journalctl logs for a specific time range.

-b -1 on a volatile journal. There is no previous boot to read, because the previous boot’s journal was in /run and /run did not survive. See finding out why a Linux server rebooted.

The files journalctl skipped without stopping

A fifth case hides inside the other four. journalctl warns and carries on when an individual file is unusable:

Journal file /var/log/journal/.../[email protected] is truncated, ignoring file.
Journal file /var/log/journal/.../[email protected] corrupted, ignoring file.
Journal file ... uses an unsupported feature, ignoring file.
Too many journal files (limit is at 7168) in scope, ignoring file '...'.

Each is a warning. The exit code stays 0 and the rest of the journal prints normally. On a busy terminal these scroll past the output you asked for and you never see them.

Check the whole set before trusting a search that came back thin:

sudo journalctl --verify

Corruption after an unclean shutdown is common and mostly harmless — journald archives the bad file and opens a new one. The entries in the bad file are the ones you lose. A file whose name ends in ~ is one journald marked this way, which is also why --file '*.journal' misses exactly the file you want after a crash. Use --file '*.journal*'.

The journal you cannot read is the one on the host that broke

Every fix above assumes you can still get a shell on the machine. The times you most want the log are the times you cannot: the disk filled, the host is unreachable, someone rebuilt it.

A copy on another machine has none of these failure modes. Install the CL Agent and point it at your server:

URL = "https://logs.example.com/api/v1/ingest_logs/YOUR-SOURCE-TOKEN"

The agent reads the journal and posts it. It advances its cursor only after the server accepts a batch, so a restart or a network blip does not drop the lines written meanwhile.

Then hear about it instead of discovering it

The worst version of “No journal files were found” is finding out a week later that a host stopped shipping. That is a rule you can write once.

Create an alert rule on the source, set it to Alert on empty, and give it this query:

SELECT 1 FROM logs
WHERE timestamp > CAST(strftime('%s','now','-15 minutes') AS INTEGER)
LIMIT 1;

Alert-on-empty inverts the usual test: the rule fires when the result set is empty, which here means the host has sent nothing for fifteen minutes. Rules are evaluated every five minutes.

SELECT 1 ... LIMIT 1 is the right shape for every rule on this server. The alert engine calls rows.Next() once and never reads the columns, so selecting anything else is work nobody looks at.

A live host is noisy enough that fifteen minutes of silence means something. A quiet one needs a longer window, or it will page you at three in the morning for nothing.

Where to go next

💌 Get notified on new features and updates

Only sent when a new version is released. Nothing else.