Fix "Job for X.service failed because the control process exited with error code"

Quick fix

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

StatusMeaningLook at
status=1/FAILUREProgram reported a generic errorJournal lines from the program
status=203/EXECCould not execute ExecStartPath, execute bit, shebang, noexec mount
status=200/CHDIRWorkingDirectory= missingDirectory exists and is accessible
status=217/USERUser= does not existgetent passwd username
status=226/NAMESPACESandboxing path missingReadWritePaths= and similar point to existing paths
Result: timeoutDid not start in timeType= mismatch, slow dependency
Result: oom-killKilled for memoryOOM killer, MemoryMax=
Result: core-dump / signalProgram crashedcoredumpctl 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/system via systemctl edit.
  • Service names differ: Apache is apache2 on Debian/Ubuntu and httpd on Fedora/Arch; MySQL/MariaDB is mysql or mariadb.

How to prevent it

  • Run the daemon's config test before every restart, or use reload, which keeps the old config running if the new one is invalid for most daemons.
  • Use systemctl edit drop-ins instead of editing vendor unit files, so package updates do not overwrite your changes.
  • Add Restart=on-failure to your own services, and monitor systemctl --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.