Fix "Job for X.service failed because the control process exited with error code"
The message is generic; the real error is in the journal. Read it, fix what it says (usually a config error or a port already in use), then restart.
sudo journalctl -xeu nginx.service --no-pager | tail -40
sudo systemctl status nginx.service
# after fixing:
sudo systemctl daemon-reload
sudo systemctl reset-failed nginx.service
sudo systemctl restart nginx.service
Replace nginx with your service name. The full message:
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
Variants end with because a timeout was exceeded, because the service did not take the steps required by its unit configuration, or because a fatal signal was delivered to the control process; the diagnosis is the same.
What the error means
systemctl asked systemd to start the unit, systemd ran the program in ExecStart= (or ExecStartPre=), and it exited with a non-zero code. systemctl only reports that the job failed; it does not know why. The program itself printed the reason to the journal. systemd basics explains units and the journal if those terms are new.
Step 1: read status and the journal
systemctl status nginx.service
Example output:
Ă— nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Fri 2026-10-16 09:12:03 UTC; 5s ago
Process: 3120 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
journalctl -xeu nginx.service
nginx[3120]: nginx: [emerg] unknown directive "server_nme" in /etc/nginx/sites-enabled/site:3
nginx[3120]: nginx: configuration file /etc/nginx/nginx.conf test failed
Look at the first error lines from the program, not the systemd summary at the end. The journalctl cheat sheet has more filters (-b, --since, -p err).
What the status code tells you
| Status | Meaning | Look at |
|---|---|---|
status=1/FAILURE | Program reported a generic error | Journal lines from the program |
status=203/EXEC | Could not execute ExecStart | Path, execute bit, shebang, noexec mount |
status=200/CHDIR | WorkingDirectory= missing | Directory exists and is accessible |
status=217/USER | User= does not exist | getent passwd username |
status=226/NAMESPACE | Sandboxing path missing | ReadWritePaths= and similar point to existing paths |
Result: timeout | Did not start in time | Type= mismatch, slow dependency |
Result: oom-kill | Killed for memory | OOM killer, MemoryMax= |
Result: core-dump / signal | Program crashed | coredumpctl info |
Cause 1: a configuration error
The most common cause by far, especially right after editing a config. Most daemons have a test mode that prints the exact file and line; run it before restarting:
sudo nginx -t
sudo apachectl configtest # Debian/Ubuntu: apache2ctl configtest
sudo sshd -t
sudo named-checkconf
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo postfix check
For YAML or JSON configs, a tab character or a missing quote is a frequent culprit. Fix the reported line, re-run the test, then restart.
Cause 2: port already in use
The journal shows bind() to 0.0.0.0:80 failed (98: Address already in use) or similar. Another program, or another instance of the same one, already holds the port:
sudo ss -ltnp 'sport = :80'
Stop the other service or change the port. Full walkthrough: bind: Address already in use.
Cause 3: permissions, ownership or missing files
Errors like Permission denied, No such file or directory or could not open log file mean the service user cannot reach a file it needs. Check the user in the unit (systemctl cat name.service | grep -i user) and test access as that user:
sudo -u www-data test -r /etc/ssl/private/site.key && echo ok
namei -l /var/www/site/index.html
namei -l shows the permissions of every directory along the path, which is where problems usually hide. Fix ownership with chown rather than loosening permissions (never chmod 777); see file permissions.
On Fedora and openSUSE Leap 16 (SELinux), and on Ubuntu/Debian with AppArmor profiles, a mandatory access control denial looks like a permission error even when the file permissions are fine. Check sudo ausearch -m avc -ts recent (SELinux) or journalctl -k | grep -i apparmor, and fix the label with restorecon -Rv /path or the appropriate semanage rule instead of disabling SELinux.
Cause 4: a broken custom unit file
For units you wrote yourself, check the unit with systemd's verifier and view the merged result including drop-ins:
systemd-analyze verify /etc/systemd/system/myapp.service
systemctl cat myapp.service
Common mistakes: a relative path in ExecStart= (it must be absolute), shell syntax like pipes or && without wrapping in /bin/sh -c, Type=forking for a program that stays in the foreground (use Type=simple or exec), and environment variables from your shell profile that do not exist under systemd (set them with Environment= or EnvironmentFile=). Always run sudo systemctl daemon-reload after editing. The systemctl cheat sheet lists the related commands.
Cause 5: start request repeated too quickly
If the service crashed repeatedly, systemd stops trying and shows Start request repeated too quickly. This is a symptom; scroll up in journalctl -u to the first failure. After fixing it, clear the counter:
sudo systemctl reset-failed myapp.service
sudo systemctl start myapp.service
Distro-specific notes
- Debian/Ubuntu/Mint: packages start services on install; a failing post-install start makes apt print dpkg returned an error code (1). Fix the service, then run
sudo dpkg --configure -a. - Fedora/openSUSE: services are not started on install; enable them with
sudo systemctl enable --now name. Remember to open the port in firewalld. - Arch: same as Fedora; unit files are in
/usr/lib/systemd/system, and your overrides go in/etc/systemd/systemviasystemctl edit. - Service names differ: Apache is
apache2on Debian/Ubuntu andhttpdon Fedora/Arch; MySQL/MariaDB ismysqlormariadb.
How to prevent it
- Run the daemon's config test before every
restart, or usereload, which keeps the old config running if the new one is invalid for most daemons. - Use
systemctl editdrop-ins instead of editing vendor unit files, so package updates do not overwrite your changes. - Add
Restart=on-failureto your own services, and monitorsystemctl --failed.
Frequently asked questions
How do I see why a systemd service failed?
Run journalctl -xeu name.service and read the lines just before "Failed to start". The service's own error message (config syntax, port in use, missing file) is there; systemctl status only shows the last few lines.
What does "start request repeated too quickly" mean?
The service crashed several times in a row and systemd stopped retrying. Fix the underlying error, then run systemctl reset-failed name.service before starting it again.
What does status=203/EXEC mean?
systemd could not execute the program in ExecStart=: the path is wrong, the file is not executable, or a script has a bad shebang line.
I edited the unit file but nothing changed. Why?
systemd caches unit files. Run sudo systemctl daemon-reload after every edit, then restart the service.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.