Start Request Repeated Too Quickly: The Real Fix, Not Just reset-failed
You deploy, the service will not come up, and systemctl status hands you this:
Start request repeated too quickly.
Failed with result 'exit-code'.
So you do what the top search result says: systemctl reset-failed, then systemctl start. It starts. You move on. And it dies again ten minutes later, because you did not fix anything. You cleared a counter. The service is still crashing, systemd is just telling you it has given up counting.
Here is the thing almost every answer to this error gets backwards: "Start request repeated too quickly" is not the problem, it is systemd protecting you from the problem. Your service is crash-looping. systemd noticed, and stopped hammering it. The message is a symptom of a crash that already happened five times. The fix is to find that crash, not to silence the messenger.
This message means your unit crashed and restarted more than StartLimitBurst times (default 5) within StartLimitIntervalSec (default 10s), so systemd rate-limited it. Do not just run reset-failed and restart. Instead:
- Read the real crash:
journalctl -u SERVICE -xe --no-pager. The genuine error is a few lines above the "repeated too quickly". - Fix the root cause (bad
ExecStartpath, missing file, port in use, wrong permissions, dependency ordering). - Then
systemctl reset-failed SERVICEandsystemctl start SERVICE. - Verify with
systemctl status SERVICEshowingactive (running)and a stable uptime.
Never "fix" it with Restart=always and RestartSec=0. That removes the brake and lets a broken service burn CPU and fill your disk with logs forever.
The exact message and what each half means
systemd[1]: myapp.service: Scheduled restart job, restart counter is at 5.
systemd[1]: myapp.service: Start request repeated too quickly.
systemd[1]: myapp.service: Failed with result 'exit-code'.
systemd[1]: Failed to start My Application.
Read it bottom to top. "Failed to start" is the conclusion. "Start request repeated too quickly" is why systemd refused this attempt. "restart counter is at 5" is the actual story: your service already started and died five times, and systemd is now declining to try a sixth time within the window. The crash you care about happened before any of these lines. Scroll up.
Why systemd does this at all
systemd has a start rate limiter, and it is a feature, not an obstacle. Two settings, both in the [Unit] section (this placement trips people up), control it:
StartLimitIntervalSec, default 10 seconds, the sliding window.StartLimitBurst, default 5, the allowed starts inside that window.
If a unit is (re)started more than StartLimitBurst times within StartLimitIntervalSec, systemd stops trying and enters the failed state with this message. Without this brake, a service that crashes instantly on startup combined with Restart=always would restart thousands of times a second, pinning a CPU core and writing gigabytes of identical crash logs until the disk fills. The rate limiter is what turns an infinite tight loop into a clear, visible failure. It is doing you a favour.
The fix, in numbered steps
Step 1: Read the real crash, not the limit message
The single most useful command here shows the full journal for the unit with the crash context:
journalctl -u myapp.service -xe --no-pager
-x adds explanatory help text, -e jumps to the end, --no-pager dumps it so you can scroll. Ignore the "repeated too quickly" lines. Look just above them for the actual exit: a Python traceback, exec: not found, Permission denied, Address already in use, No such file or directory. That line is your bug. If the process writes its own logs elsewhere, check there too, sometimes the app dies before systemd captures anything useful.
Step 2: Match the crash to its root cause
Nearly every case is one of these, and the journal line tells you which:
| What the journal shows | Root cause | Fix |
|---|---|---|
No such file or directory / exec: ... not found | Wrong ExecStart path or interpreter | Use an absolute path; check the binary/venv actually exists there |
Permission denied | User= cannot execute the binary or read a file | Fix ownership/mode, or run as the right user |
Address already in use | Port taken by another process/old instance | Free the port; find it with ss -ltnp |
| App traceback about a missing env/config | Config file or env var absent under systemd | Set EnvironmentFile=; do not assume your shell's env |
| Starts before a dependency is ready | Ordering: DB/network not up yet | After= / Requires= the dependency |
The environment one catches almost everyone. A service under systemd does not inherit your interactive shell's PATH, virtualenv, or exported variables. It runs with a minimal environment. "It works when I run the command by hand" is expected and misleading, because by hand you have your whole shell environment. Give systemd the environment explicitly:
[Service]
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/.venv/bin/python -m myapp
WorkingDirectory=/opt/myapp
Step 3: Fix the cause, then clear the counter
Only after you have corrected the underlying crash do you clear systemd's failure state. Reload if you edited the unit file, then reset and start:
sudo systemctl daemon-reload # only if you edited the .service file
sudo systemctl reset-failed myapp.service
sudo systemctl start myapp.service
reset-failed zeroes the restart counter so the limiter forgets the earlier crashes. On its own it fixes nothing, which is the entire point of this article, but it is the correct final step once the real bug is gone.
Verification: prove it is actually up and staying up
systemctl status myapp.service
You want Active: active (running) and, crucially, an uptime that keeps growing when you check again a minute later. A service that shows "running" for two seconds and flips back to failed is still crash-looping, just slowly enough to dodge the limiter. Confirm stability over time:
# watch it for a minute; the "since" time should not reset
watch -n 5 'systemctl show -p ActiveState -p ExecMainStartTimestamp myapp.service'
If ExecMainStartTimestamp keeps changing, the process is still dying and being restarted. Go back to journalctl. If it holds steady, you are done.
What people get wrong
reset-failedin a loop. This is the top-ranked advice and it is a placebo. It clears the counter without touching the crash, so the service loops right back into the failed state. It belongs at the end of the fix, never as the fix.- Raising
StartLimitBurstto a huge number. This does not make the service work, it just lets it crash more times before systemd gives up. You have widened the window on a broken process. Fix the process. Restart=alwayswithRestartSec=0as "reliability". This is actively harmful. With no delay and the limiter disabled or widened, a service that dies on startup will restart as fast as the CPU allows, spiking load and flooding the journal. As I argue in a systemd unit file that actually keeps it running,Restart=alwaysis not reliability, it is a way of never finding out why your app crashed. UseRestart=on-failurewith a saneRestartSeclike5.- Deleting the limiter with
StartLimitIntervalSec=0. That removes the only thing turning an infinite crash loop into a visible failure. Keep the brake.
When it is still broken
- The journal shows nothing useful before the limit. The process dies before it logs. Run the exact
ExecStartcommand by hand as the service user (sudo -u appuser /opt/myapp/.venv/bin/python -m myapp) and read what it prints. This reproduces the crash outside systemd. - It works by hand but not under systemd. That is almost always environment or working directory. Compare
envin your shell with what the unit provides, and setWorkingDirectory=andEnvironmentFile=explicitly. - It crashes only after some seconds. That is not a startup bug, it is a runtime one, and it may be the kernel, not your code. If the process vanishes with no traceback, check for the OOM killer, covered in what really happens when your server runs out of RAM.
- It depends on the network or a database that is not ready. Add proper ordering (
After=network-online.targetplusWants=network-online.target, orAfter=your DB unit) rather than restarting until the dependency happens to be up.
The mindset that fixes this permanently: the rate limiter is systemd doing its job. When you see "Start request repeated too quickly", read it as "your service crashed five times, here is where I stopped". Then go find the crash. If you have a container showing the same loop shape with no logs, the diagnostic method transfers directly, see CrashLoopBackOff with no logs.
Frequently asked questions
- What does 'Start request repeated too quickly' mean in systemd?
- It means your service crashed and was restarted more times than StartLimitBurst (default 5) within StartLimitIntervalSec (default 10 seconds), so systemd stopped trying and marked the unit failed. The message is not the bug; it is systemd protecting you from an infinite crash loop. The real error is in journalctl a few lines above this message.
- Does systemctl reset-failed fix the problem?
- No. reset-failed only zeroes the restart counter so systemd will attempt the service again. It does nothing about why the service was crashing, so the service simply loops back into the failed state. reset-failed is the correct final step after you have fixed the underlying crash, never the fix itself.
- How do I find the actual crash behind the rate limit message?
- Run journalctl -u SERVICE -xe --no-pager and look at the lines just above 'Start request repeated too quickly'. You are looking for the real exit reason: a traceback, 'No such file or directory', 'Permission denied', or 'Address already in use'. If the app logs nothing, run the ExecStart command by hand as the service user to reproduce the crash outside systemd.
- Should I use Restart=always to keep the service up?
- No, that is a common but harmful anti-fix. Restart=always with RestartSec=0 lets a service that dies on startup restart as fast as the CPU allows, spiking load and flooding the journal, and it hides the real crash. Use Restart=on-failure with a sane RestartSec such as 5, keep the start limiter enabled, and fix the actual cause of the crash.