Skip to content
LinuxFix Published Updated 3 min readViews unavailable

Fixing 'start-limit-hit' Errors in systemd

systemctl reports start-limit-hit when systemd's crash-loop protection trips — clearing the rate limit is a distinct step after fixing the real cause.

systemctl start myservice reports Failed to start myservice.service: Unit myservice.service not found — no wait, more precisely: “start request repeated too quickly” or “start-limit-hit” means systemd has deliberately stopped trying to start a unit that’s failed too many times in a short window.

Step 1: check the unit’s actual failure reason first

systemctl status myservice
journalctl -u myservice -n 50

The rate limit is systemd protecting against a genuine crash loop — fixing why the service keeps failing is the real work; clearing the rate limit alone just lets it fail rapidly again.

Step 2: identify and fix the actual underlying problem

Common causes behind the repeated failures: a missing configuration file, an unavailable dependency (a database the service can’t reach yet), incorrect permissions, or a bug triggered on every startup — the journal output from Step 1 should point at one of these directly.

Step 3: check the unit’s own rate-limit configuration

[Unit]
StartLimitIntervalSec=60
StartLimitBurst=3

This unit fails permanently after 3 restart attempts within 60 seconds — worth knowing these values exist and are adjustable, though the fix is rarely “just allow more retries.”

Step 4: reset the failed state once the real cause is fixed

systemctl reset-failed myservice

This clears systemd’s internal failure counter for the unit — required after fixing the underlying issue, since systemd won’t attempt a fresh start cycle until this counter is cleared.

Step 5: start the service again

systemctl start myservice

Step 6: watch it through a few natural restart cycles if it’s meant to restart on its own

journalctl -u myservice -f

For a service configured with Restart=on-failure, confirm it now survives whatever transient condition (a slow-starting dependency) previously triggered the loop, rather than hitting the same limit again after the reset.

Step 7: add an explicit dependency if the real cause was a race at boot

[Unit]
After=postgresql.service
Requires=postgresql.service

A service crash-looping specifically at boot, because a dependency (a database, a network mount) isn’t ready yet, is fixed properly by declaring that dependency explicitly — not by increasing the restart burst limit to outlast the race.

Why reset-failed is easy to forget

Fixing the root cause and restarting the service manually often works once — but systemd’s own internal failure counter persists across that manual start, meaning the very next automatic restart attempt (from a boot, or a monitoring system triggering a restart) can immediately hit the same limit again if it was never cleared. Making reset-failed a standard part of the fix, not an optional afterthought, avoids the confusing “I fixed it and it broke again” experience.

Step 8: check whether StartLimitAction makes this more urgent than it looks

[Unit]
StartLimitAction=reboot

By default, exhausting a unit’s start limit simply leaves it failed and inert — but StartLimitAction can be configured to trigger reboot, reboot-force, or poweroff instead, intended for units where “just stay down” isn’t an acceptable failure mode. A service crash-looping at boot with this option set can put a machine into a genuine reboot loop, restarting, hitting the same start limit, and rebooting again indefinitely — which turns diagnosing the underlying failure (Step 1-2) into a race against the next automatic reboot, and is worth checking for immediately with systemctl cat myservice if a system is rebooting repeatedly rather than simply failing a service and stopping.

Step 9: watch restart counts and timestamps directly rather than inferring them

systemctl show myservice -p NRestarts,ActiveEnterTimestamp,InactiveEnterTimestamp

Rather than reconstructing how many times a unit has restarted and when from journal timestamps by hand, systemctl show with these specific properties reports systemd’s own internal counters and state-transition times directly — useful both for confirming a fix actually stopped the crash loop (NRestarts staying flat after the fix, rather than continuing to climb) and for establishing exactly when the failing pattern first began relative to some other change on the system.

Related:

Sources:

Comments