Skip to content
ohsudo, Home
Linux

"Job for nginx.service failed because the control process exited with error code": how to find the cause

Fix "Job for X.service failed because the control process exited with error code": read systemctl status and journalctl, test the config, and fix the usual causes.

Beginner5 min readApplies to systemd 249+ · Ubuntu · Debian · RHEL / Rocky / AlmaLinux · nginx · Apache · any systemd service

by OhSudo ··

Not sure this is your cause?Find it step by step: Website down →

Part of a learning path:Linux: from zero to fixing a server

You start or restart a service and systemd answers:

$ sudo systemctl start nginx
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.

The message is the same for every service (nginx, Apache, PostgreSQL, your own app), and it only says that something failed. systemd ran a command to start the service, the command exited with an error, and systemd gave up. Why it failed is in the two places the message itself points to: systemctl status and the journal.

  1. systemctl start nginx
  2. ExecStartthe service's start command
  3. Exited with an errorunit failed: see journalctl(breaks here)
systemd ran the command that starts the service, the command exited with an error, and systemd gave up. The message is the same for every service; the reason is in status and the journal.

TL;DR

Terminal window
systemctl status nginx --no-pager # state, exit status, last log lines
sudo journalctl -xeu nginx --no-pager # the full log of the failed start
sudo nginx -t # nginx: test the config, shows file and line

Then fix what the log says, test again, and start the service.

1. Read the status

Terminal window
systemctl status nginx --no-pager
× 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 Sun 2026-11-01 09:12:40 UTC; 2min ago
Nov 01 09:12:40 ohsudo systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Nov 01 09:12:40 ohsudo nginx[702]: nginx: [emerg] unknown directive "servername" in /etc/nginx/sites-enabled/default:5
Nov 01 09:12:40 ohsudo nginx[702]: nginx: configuration file /etc/nginx/nginx.conf test failed
Nov 01 09:12:40 ohsudo systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE

Three things to look at:

  • Active: failed (Result: …) — exit-code means a command returned an error; signal means it was killed; start-limit-hit means systemd stopped trying (section 5).
  • status=… on the “exited” line — the exit code. Codes above 200 come from systemd itself and have names (section 4).
  • The lines from the service itself (here nginx[702]: …) — usually the real error, in the program’s own words.

systemctl status shows only the last few lines. If they are cut, or you need more, read the journal.

2. Read the journal

Terminal window
sudo journalctl -xeu nginx --no-pager

-u nginx limits it to this unit, -e jumps to the end, and -x adds explanations to systemd’s messages. Read from the bottom up to the first line that comes from the program, not from systemd[1]. With --since "10 min ago" you can skip older starts.

Some services also write to their own log file, and the most useful message may be only there: /var/log/nginx/error.log, /var/log/apache2/error.log (/var/log/httpd/ on RHEL), /var/log/postgresql/.

3. Test the configuration

Most of the time, the error is a typo in a config file someone just edited. Most daemons can check their own configuration without starting, and they tell you the file and the line:

Terminal window
sudo nginx -t
nginx: [emerg] unknown directive "servername" in /etc/nginx/sites-enabled/default:5
nginx: configuration file /etc/nginx/nginx.conf test failed

Fix the line, test again, and start the service only when the test passes:

Terminal window
sudo sed -i 's/servername/server_name/' /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl start nginx

The same idea for other services:

Service Config test
nginx sudo nginx -t
Apache sudo apachectl configtest
OpenSSH sudo sshd -t
HAProxy sudo haproxy -c -f /etc/haproxy/haproxy.cfg
BIND sudo named-checkconf
PHP-FPM sudo php-fpm8.3 -t (the version is part of the name on Debian/Ubuntu; php-fpm -t on RHEL)

Warning

reload vs. restart with a broken config. systemctl reload nginx tests the new config first, and if it fails, nginx keeps running with the old one. systemctl restart nginx stops nginx first — if the new config is broken, it doesn’t come back, and your site is down. Test before you restart: sudo nginx -t && sudo systemctl restart nginx.

4. The usual causes

The port is taken. bind() to 0.0.0.0:80 failed (98: Address already in use) — another program already listens there. See find who is using port 80.

A file is missing or can’t be read. A certificate, a key, a log folder, a socket path:

nginx: [emerg] cannot load certificate "/etc/ssl/certs/example.com.crt": BIO_new_file() failed (… No such file or directory …)

Check the path from the message with ls -l, and check that the service’s user can read it. On RHEL-family systems, a file with the wrong SELinux label gives Permission denied even with correct permissions: sudo restorecon -v <file>.

The program can’t be started at all. For your own services, the exit status has a name that tells you which step failed:

Exit status Meaning Check
203/EXEC The program in ExecStart= doesn’t exist or isn’t executable The path in systemctl cat <service>, then ls -l on it
217/USER The user in User= doesn’t exist id <user>
200/CHDIR WorkingDirectory= doesn’t exist ls -ld <folder>
1/FAILURE The program itself exited with an error Its own lines in the journal

You edited the unit file but systemd still uses the old one. systemd warns you about it:

Warning: The unit file, source configuration file or drop-ins of myapp.service changed on disk. Run 'systemctl daemon-reload' to reload units.

Run sudo systemctl daemon-reload, then start the service again.

5. “Start request repeated too quickly”

myapp.service: Start request repeated too quickly.
myapp.service: Failed with result 'start-limit-hit'.

A service that crashes and restarts in a loop is stopped after a few tries (by default, 5 starts in 10 seconds). This isn’t the cause, only a symptom — find the real error further up in the journal. After you fix it, clear the counter and start again:

Terminal window
sudo systemctl reset-failed myapp
sudo systemctl start myapp

Shell, we have a problem!

Similar, but different: Failed to start nginx.service: Unit nginx.service not found. means the service isn’t installed, or its name is different (apache2 on Debian/Ubuntu, httpd on RHEL; ssh vs. sshd). systemctl list-unit-files | grep <name> shows the real name. Interactive authentication required means you forgot sudo. System has not been booted with systemd means systemd isn’t running there at all: see that article. On RHEL, a service that fails with Permission denied while its files look fine is often SELinux. For the commands around this, see the systemctl and journalctl Cheat Sheet. To practice this safely, try the lesson Nginx won’t start.

$ ./practice.sh

Practice this in the terminal

Open the Terminal Playground with this article’s scenario loaded. It is safe and runs in your browser.

Open the terminal →

Found this useful? Share it.

Found a mistake? Let us know at contact@ohsudo.com.

Tools

Try it yourself

Articles

Related articles