Home › Linux & shell

status=203/EXEC — how to fix

myapp.service: Main process exited, code=exited, status=203/EXEC
myapp.service: Failed to execute /opt/myapp/start.sh: Permission denied
myapp.service: Failed at step EXEC spawning /opt/myapp/start.sh: No such file or directory

Quick fix: Run journalctl -u myapp -n 20 to see the exact reason after 'Failed at step EXEC'. Use an absolute path in ExecStart, chmod +x the file, make sure the script starts with a valid shebang like #!/bin/bash and has LF line endings (sed -i 's/\r$//' start.sh), then sudo systemctl daemon-reload && sudo systemctl restart myapp.

What it means

Exit status 203 is systemd's own code for EXEC: it forked the service process, but the execve() of the ExecStart= command failed. Your program never ran, so its own logs are empty. The real reason is in the journal, right next to the status line:

sudo systemctl status myapp
journalctl -u myapp -n 30 --no-pager

Look for Failed at step EXEC spawning <path>: <reason> or Failed to execute <path>: <reason>. The reason maps to the fixes below.

Cause 1: No such file or directory — wrong path

ExecStart= needs an absolute path to the executable (systemd 239+ allows a bare command name only if it's in systemd's fixed search path, and it does not use your shell's PATH).

# wrong
ExecStart=node server.js
ExecStart=~/app/start.sh
# right
ExecStart=/usr/bin/node /opt/myapp/server.js

Find the real path with command -v node. Tools installed with nvm, pyenv or in a virtualenv live in your home directory; use their full path, e.g. /home/app/.nvm/versions/node/v20.11.0/bin/node or /opt/myapp/venv/bin/python.

~ and $HOME are not expanded. Shell features (pipes, &&, redirects) don't work either; wrap them in /bin/bash -c '...' or a script.

Cause 2: No such file or directory — but the file exists

For a script this means the interpreter from the shebang is missing. Typical reasons:

head -1 /opt/myapp/start.sh | od -c | head -2   # look for \r
sed -i 's/\r$//' /opt/myapp/start.sh

(Or paste the file into the line ending inspector.) - A shebang pointing to a path that doesn't exist on this machine (#!/usr/local/bin/python3). See bad interpreter: No such file or directory. - A binary built for another architecture or against a missing dynamic loader (e.g. a glibc binary on Alpine).

Cause 3: Permission denied

ls -l /opt/myapp/start.sh
sudo chmod +x /opt/myapp/start.sh

Also check:

Cause 4: Exec format error

The file has no shebang line at all, or it's a binary for another CPU architecture. Add #!/bin/bash (or the right interpreter) as the very first line, with nothing before it, or run it explicitly: ExecStart=/bin/bash /opt/myapp/start.sh.

Apply the fix

sudo systemctl daemon-reload
sudo systemctl restart myapp
sudo systemctl status myapp

Test the exact command as the service user first, which reproduces most problems instantly:

sudo -u app /opt/myapp/start.sh

If the service starts and then fails repeatedly, you'll see start request repeated too quickly instead; that's an application problem, not 203.

Last updated 2026-11-08.