How to Fix Linux systemd Service Entering "Auto-Restart Loop" Due to Exit Status Code
Quick answer
A systemd service keeps restarting over and over, cycling through start-crash-restart repeatedly instead of running stably, until systemd eventually gives up...
A systemd service keeps restarting over and over, cycling through start-crash-restart repeatedly instead of running stably, until systemd eventually gives up and marks it as failed entirely. This means the underlying process is genuinely crashing shortly after each start β systemd's restart behavior is working exactly as configured, but something in your application or its configuration is causing it to exit almost immediately every time.
The Problem
Checking the service status shows a rapid cycle of activation and failure:
$ systemctl status myapp
β myapp.service
Loaded: loaded
Active: activating (auto-restart) (Result: exit-code) since Thu 2026-08-07 14:22:03 UTC; 2s ago
Process: 8821 ExecStart=/usr/local/bin/myapp (code=exited, status=1/FAILURE)
After enough rapid restart attempts, systemd stops trying entirely:
$ systemctl status myapp
β myapp.service
Active: failed (Result: start-limit-hit)
Aug 7 14:22:15 myserver systemd[1]: myapp.service: Start request repeated too quickly.
Aug 7 14:22:15 myserver systemd[1]: myapp.service: Failed with result 'start-limit-hit'.
Why It Happens
systemd's Restart= directive automatically restarts a service after it exits, which is genuinely useful for recovering from transient failures β but if the underlying cause of the crash isn't transient (a persistent configuration error, a missing dependency, a bug that triggers immediately on every startup), the service just crashes again immediately after each restart, cycling rapidly until StartLimitBurst is exceeded and systemd gives up. The actual root cause of the crash itself varies widely:
- A configuration error or missing environment variable causing the application to fail its own startup validation and exit immediately, every single time.
- A missing dependency that isn't ready yet when the service starts β for example, the application tries to connect to a database that hasn't finished starting up itself, especially in a boot sequence where service ordering wasn't correctly configured.
- A port already in use by another process, or by a previous instance of the same service that didn't fully release the port before systemd tried to start a new instance.
- A genuine application bug triggering deterministically on every startup, unrelated to any external environmental factor.
The Fix
Always start by reading the actual application logs, not just systemd's own status summary, since the real error is almost always in the application's own output rather than in anything systemd itself reports:
journalctl -u myapp -n 50 --no-pager
This shows the last 50 log lines from the service, which typically include the application's own error message explaining exactly why it exited. Address whatever specific error is shown β a missing config file, an unreachable dependency, invalid syntax in a config, or whatever else the log reveals.
For dependency-ordering issues (the application starting before something it depends on is ready), explicitly declare the dependency relationship in the unit file rather than relying on coincidental timing:
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=postgresql.service network-online.target
Wants=postgresql.service
Requires=network-online.target
After= controls ordering, while Requires=/Wants= control whether systemd should actually attempt to start the dependency if it isn't already running β using both together for a genuine hard dependency ensures the application doesn't even attempt to start before its dependency is up.
If the crash is due to a port conflict from a lingering previous instance, add a brief startup delay or an explicit pre-start check that waits for the port to actually be free:
[Service]
ExecStartPre=/bin/sh -c 'while fuser 8080/tcp 2>/dev/null; do sleep 1; done'
ExecStart=/usr/local/bin/myapp
Reload systemd's configuration after any unit file changes:
sudo systemctl daemon-reload
sudo systemctl reset-failed myapp
sudo systemctl start myapp
reset-failed is necessary since systemd remembers the "failed due to start-limit-hit" state and won't attempt a fresh start until it's explicitly cleared.
If restarts genuinely need to happen but you want more breathing room between attempts (giving a transient issue, like a dependency still starting up, more time to resolve on its own), tune the restart timing and burst limits rather than restarting as fast as possible every time:
[Service]
Restart=on-failure
RestartSec=10
StartLimitIntervalSec=300
StartLimitBurst=5
This waits 10 seconds between each restart attempt and allows up to 5 attempts within a 5-minute window before giving up, rather than systemd's more aggressive default rapid-retry behavior.
Still Not Working?
If the application logs don't reveal an obvious cause, run the executable manually and directly, exactly as systemd would invoke it, which often surfaces error output more clearly and immediately than reading through journalctl's formatted log entries:
# Check exactly how systemd invokes it
systemctl cat myapp | grep ExecStart
# Then run manually with the same user and environment
sudo -u myapp-user /usr/local/bin/myapp
Running it this way, outside of systemd's process supervision entirely, often reveals startup errors far more directly and immediately than sifting through journal entries, and it also rules out any systemd-specific environment differences (a stripped-down PATH, missing environment variables normally set in your interactive shell) as a contributing factor to the crash.