How do I end my program with a chosen exit code when something fails?
← Error Handling and Exceptions · Ref: Q1432
Throw an Exception that carries the exit code, and do not catch it. When it reaches the top of the program, the program prints it on stderr, runs every finally block and the application teardown, and then exits with that code.
throw Exception("No settings file named", 3)
The program below exits 3. The 'Cleanup ran' line is printed by a finally block, so cleanup happens before the process ends. stderr gets one line, with no Java stack trace: 'Exception in thread "main" Exception: No settings file named: Exit Code: 3'.
RULES
- The code is the one on the exception that reaches the top. If it has no code, the program exits 1 (see Q1433).
- A catch that handles the exception ends that failure, so its code no longer applies. To keep the code, let the exception pass or throw it again (see Q1436).
- A subclass of Exception passes the code to super(reason, exitCode), and it behaves the same way.
- You cannot use Panic for this. User code cannot create a Panic - it has no constructors you can call - so 'throw Panic(...)' is E50060, and a Panic always exits 1 (see Q1434).
When the run is started by the ek9 command, a status from your program is the program's own and not the compiler's (see Q1437).
See Q1431 for every way a program sets its exit status. See Q136 for throwing exceptions.
Example
defines module qa.errorhandling.uncaughtexitcode defines function loadSettings() -> fileName as String <- rtn as String? if not fileName? throw Exception("No settings file named", 3) rtn: `Loaded ${fileName}` defines program UncaughtExitCodeDemo() stdout <- Stdout() stdout.println(loadSettings("app.properties")) try stdout.println("Loading settings with no file name") stdout.println(loadSettings(String())) finally stdout.println("Cleanup ran before the process ended")
Common mistakes
E50060 — Panic is raised only by the language and has no constructors user code can call, so 'Panic(...)' does not resolve - and it is not an Exception, so it could not be thrown anyway. An uncaught Exception carrying the code ends the program with that code. See ek9 -h E50060 for details.
Incorrect:
throw Panic("No settings file named", 3)
Correct:
throw Exception("No settings file named", 3)
Other ways to ask this
- What happens to the exit code of an Exception nothing catches?
- How do I exit with code 3 when a configuration file is missing?
- Does Exception(reason, exitCode) really set the process exit status?
- How do I stop an EK9 program with a specific error code?
Coming from another language?
Java: an uncaught exception always exits 1 whatever it carries, so a chosen code needs System.exit(n). Python: raise SystemExit(3). Rust: std::process::exit(3) skips destructors. EK9: Exception("reason", 3) that nothing catches exits 3, after finally blocks and teardown.
Keywords: finally, teardown, exitCode, uncaught, exit code, throw, exception, stderr, process status