Fixing 'start-limit-hit' Errors in systemd
A service refuses to start at all, and systemctl reports start-limit-hit — this is systemd's own crash-loop protection, and it requires clearing the rate limit as 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.