| title | systemd Failed to start unit | |||||
|---|---|---|---|---|---|---|
| slug | linux-systemd-failed-to-start-unit | |||||
| technologies |
|
|||||
| severity | high | |||||
| tags |
|
|||||
| related |
|
|||||
| last_reviewed | 2026-06-27 |
Failed to start myapp.service - My Application.
systemd[1]: myapp.service: Main process exited, code=exited, status=203/EXEC
systemd[1]: myapp.service: Failed with result 'exit-code'.
systemd[1]: myapp.service: Scheduled restart job, restart counter is at 5.
systemd[1]: myapp.service: Start request repeated too quickly.
Failed to start <unit> is systemd's report that a unit did not reach an active
state. It is a summary β the actionable detail is the result line that follows:
the exit status=/code=, the result (exit-code, signal, timeout,
oom-kill, protocol), and the unit's own stdout/stderr in the journal.
systemd's numeric status=NNN/NAME codes (e.g. 203/EXEC, 200/CHDIR,
217/USER) come from the service manager itself and pinpoint why the exec
failed before your program even ran. "Start request repeated too quickly" means
it has crashed enough times to trip the restart rate limit.
- systemd (service manager, unit execution)
- linux (process exec, namespaces)
high β the service is not running. For a critical daemon this is a direct
outage, and the restart loop can mask the root cause while the dependency graph
fails other units that Requires= it.
ExecStart=points at a missing/non-executable binary or wrong path β203/EXEC.- A configured
User=,Group=,WorkingDirectory=, orReadWritePaths=doesn't exist or is wrong β217/USER,200/CHDIR. - The application itself exits non-zero on bad config / missing env / unreachable
dependency β
status=1. - The unit's sandboxing (
ProtectSystem=,ReadOnlyPaths=,PrivateTmp=) blocks a path the app needs to write. - A
Type=notify/Type=forkingmismatch or a slow start hittingTimeoutStartSecβresult 'timeout'.
systemd forks a helper that sets up the unit's execution environment β user,
cgroup, namespaces, working directory, capabilities β then execve()s
ExecStart=. If that setup or the exec fails, systemd reports a 2xx status
code generated by the manager (the program never ran). If the program does run
and exits non-zero, you get its real exit status and its log lines. The
Restart= policy plus StartLimitIntervalSec/StartLimitBurst then governs
retries; once the burst limit is exceeded systemd gives up with "Start request
repeated too quickly" and leaves the unit failed. Reading systemctl status
and journalctl -u together tells you which half β manager setup vs application
β failed.
# Headline state, last exit code/result, and recent log tail
systemctl status myapp.service --no-pager -l
# Full logs for the unit from this boot (the real error lives here)
journalctl -u myapp.service -b --no-pager | tail -50
# The effective, merged unit definition (catch a bad ExecStart/User/path)
systemctl cat myapp.service
systemctl show myapp.service -p ExecStart -p User -p WorkingDirectory -p Restart
# Why it won't start: failed dependencies / ordering
systemctl list-dependencies --failed$ systemctl status myapp.service
β myapp.service - My Application
Active: failed (Result: exit-code)
Process: 4821 ExecStart=/usr/local/bin/myapp (code=exited, status=203/EXEC)
$ journalctl -u myapp.service -b | tail
systemd[1]: myapp.service: Failed at step EXEC spawning /usr/local/bin/myapp: No such file or directory
Failed at step EXEC ... No such file or directory with status=203/EXEC means
the binary path is wrong or not executable β a manager-side failure, not an app
bug. A plain status=1 with app log lines means the application chose to exit.
-
Read the journal first and act on the specific result:
203/EXECβ fix theExecStart=path;chmod +xthe binary; check it exists for the configuredUser=.217/USERβ create the missing user/group or correct the name.200/CHDIRβ create/fixWorkingDirectory=.- app
status=1β fix the config/env/dependency the app complains about.
-
If sandboxing blocks a needed path, add it to
ReadWritePaths=or relax the specific protection β minimally, not by disabling all hardening. -
After editing the unit, reload then restart:
sudo systemctl daemon-reload sudo systemctl reset-failed myapp.service # clear the rate-limit counter sudo systemctl restart myapp.service -
For timeouts, fix the readiness signal (
Type=notify+sd_notify) or raiseTimeoutStartSec=only if the start is legitimately slow.
systemctl is-active myapp.service # expect: active
systemctl status myapp.service # Active: active (running), no restart loop
journalctl -u myapp.service -f # expect steady output, no new failures- Validate
ExecStartpaths andUser=existence in CI / on deploy. - Keep
Restart=on-failurewith saneStartLimitBurstso loops surface fast. - Add hardening paths (
ReadWritePaths=) alongside the protection that needs them. - Use
Type=notifyfor accurate readiness instead of guessing timeouts. systemd-analyze verify myapp.servicein CI to catch unit syntax errors.
systemd Β· service Β· unit Β· startup Β· production