Introduction
Systemd exit code 203 (EXEC) occurs when the executable defined in the ExecStart directive of a unit file cannot be located or executed. This is one of the most common startup failures on Linux systems and typically points to a missing binary, incorrect path, wrong interpreter, or file permission problem.
Symptoms
systemctl statusshowsMain process exited, code=exited, status=203/EXEC- Journal logs contain
Failed at step EXEC spawning /path/to/binary: No such file or directory - Service enters
failedstate immediately after start attempt systemd[1]: myapp.service: Main process exited, code=exited, status=203/EXEC
Common Causes
- The binary path in
ExecStartdoes not exist or contains a typo - The script interpreter specified in the shebang line is missing
- The executable lacks the execute permission bit
- The binary is a 32-bit ELF on a 64-bit-only system without compat libraries
- SELinux or AppArmor is blocking execution of the binary
Step-by-Step Fix
- 1.Identify the failing executable path:
- 2.```bash
- 3.journalctl -u myapp.service -n 20 --no-pager
- 4.
` - 5.Look for the line containing
Failed at step EXEC spawning. - 6.Verify the binary exists at the specified path:
- 7.```bash
- 8.ls -la /usr/local/bin/myapp
- 9.which myapp 2>/dev/null || echo "Binary not in PATH"
- 10.file /usr/local/bin/myapp
- 11.
` - 12.Check file permissions and set execute bit if needed:
- 13.```bash
- 14.chmod 755 /usr/local/bin/myapp
- 15.# For scripts, also verify interpreter exists
- 16.head -1 /usr/local/bin/myapp
- 17.# If shebang is #!/usr/bin/python3, verify:
- 18.ls -la /usr/bin/python3
- 19.
` - 20.Verify systemd unit file ExecStart path:
- 21.```bash
- 22.systemctl cat myapp.service | grep ExecStart
- 23.# Fix the unit file if path is wrong
- 24.sudo nano /etc/systemd/system/myapp.service
- 25.sudo systemctl daemon-reload
- 26.
` - 27.Check SELinux/AppArmor denials:
- 28.```bash
- 29.# SELinux
- 30.ausearch -m avc -ts recent | grep myapp
- 31.# AppArmor
- 32.dmesg | grep -i apparmor | grep myapp
- 33.
` - 34.Restart the service and verify:
- 35.```bash
- 36.sudo systemctl restart myapp.service
- 37.systemctl status myapp.service
- 38.
`
Prevention
- Use absolute paths in all
ExecStartdirectives, never rely on$PATH - Add
ConditionPathExists=/usr/local/bin/myappto fail gracefully with a clear message - Include a
Type=notifyorType=simplewith properExecStartPre=checks to validate the binary before starting - Use configuration management (Ansible, Puppet) to ensure binary paths stay in sync with unit files