</>CodeWithKarani

Start Request Repeated Too Quickly: The Real Fix, Not Just reset-failed

Karani GeoffreyKarani Geoffrey6 min read

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:

  1. Read the real crash: journalctl -u SERVICE -xe --no-pager. The genuine error is a few lines above the "repeated too quickly".
  2. Fix the root cause (bad ExecStart path, missing file, port in use, wrong permissions, dependency ordering).
  3. Then systemctl reset-failed SERVICE and systemctl start SERVICE.
  4. Verify with systemctl status SERVICE showing active (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.

StartLimitIntervalSec = 10s window, StartLimitBurst = 5 0s 10s start 1 2 3 4 5 6th blocked "repeated too quickly" Each red dot is a crash. The message appears only at the 6th attempt. The bug is whatever killed dots 1 through 5.
The limiter is the last event in the chain, never the first. Investigate the crashes, not the limit.

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 showsRoot causeFix
No such file or directory / exec: ... not foundWrong ExecStart path or interpreterUse an absolute path; check the binary/venv actually exists there
Permission deniedUser= cannot execute the binary or read a fileFix ownership/mode, or run as the right user
Address already in usePort taken by another process/old instanceFree the port; find it with ss -ltnp
App traceback about a missing env/configConfig file or env var absent under systemdSet EnvironmentFile=; do not assume your shell's env
Starts before a dependency is readyOrdering: DB/network not up yetAfter= / 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-failed in 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 StartLimitBurst to 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=always with RestartSec=0 as "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=always is not reliability, it is a way of never finding out why your app crashed. Use Restart=on-failure with a sane RestartSec like 5.
  • 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

  1. The journal shows nothing useful before the limit. The process dies before it logs. Run the exact ExecStart command 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.
  2. It works by hand but not under systemd. That is almost always environment or working directory. Compare env in your shell with what the unit provides, and set WorkingDirectory= and EnvironmentFile= explicitly.
  3. 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.
  4. It depends on the network or a database that is not ready. Add proper ordering (After=network-online.target plus Wants=network-online.target, or After= 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.
#systemd#journalctl#Linux#Services#Crash Loop
Keep reading

Related articles