{"id":"a66aa3728e8ccab9","repo":"apache/kafka","slug":"statuscode-must-not-be-0","errorCode":null,"errorMessage":"statusCode must not be 0","messagePattern":"statusCode must not be 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/internals/FatalExitError.java","lineNumber":36,"sourceCode":"\nimport org.apache.kafka.common.utils.internals.Exit;\n\n/**\n * An error that indicates the need to exit the JVM process. This should only be used by the server or command-line\n * tools. Clients should never shutdown the JVM process.\n *\n * This exception is expected to be caught at the highest level of the thread so that no shared lock is held by\n * the thread when it calls {@link Exit#exit(int)}.\n */\npublic class FatalExitError extends Error {\n\n    private static final long serialVersionUID = 1L;\n\n    private final int statusCode;\n\n    public FatalExitError(int statusCode) {\n        if (statusCode == 0)\n            throw new IllegalArgumentException(\"statusCode must not be 0\");\n        this.statusCode = statusCode;\n    }\n\n    public FatalExitError() {\n        this(1);\n    }\n\n    public int statusCode() {\n        return statusCode;\n    }\n}\n","sourceCodeStart":18,"sourceCodeEnd":48,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/internals/FatalExitError.java#L18-L48","documentation":"Thrown as IllegalArgumentException by the FatalExitError(int) constructor when statusCode is 0. FatalExitError is the Error Kafka raises to request a JVM exit via Exit.exit(statusCode); status 0 conventionally means success, which contradicts the intent of a *fatal* exit, so the constructor rejects it eagerly. Any caller that wants a 'successful' shutdown should not be throwing FatalExitError at all.","triggerScenarios":"Constructing new FatalExitError(0) directly, or passing a status code read from a config/source that resolved to 0; a helper that wraps FatalExitError and forwards a default/zero status on some code path.","commonSituations":"Server or CLI tool code that maps an exit-code configuration/source to FatalExitError without validating non-zero; tests constructing FatalExitError with parameterized values that include 0; refactors where a previously-non-zero constant was changed to 0.","solutions":["Pass a non-zero status (the no-arg constructor FatalExitError() defaults to 1).","If the status originates from config/input, validate it is non-zero before constructing FatalExitError, or pick a sensible non-zero default.","Reconsider whether FatalExitError is the right vehicle if you genuinely want a clean (status 0) shutdown; use a normal return / graceful close path instead.","In tests, exclude 0 from parameterized exit-code matrices or assert that IllegalArgumentException is thrown for it."],"exampleFix":"// before\nthrow new FatalExitError(exitCode);   // exitCode may be 0\n\n// after\nif (exitCode == 0) throw new IllegalArgumentException(\"exitCode must be non-zero\");\nthrow new FatalExitError(exitCode);","handlingStrategy":"validation","validationCode":"int statusCode = ...;\nif (statusCode == 0) {\n    throw new IllegalArgumentException(\"FatalExitError requires a non-zero statusCode (use a different signal for success)\");\n}\nnew org.apache.kafka.common.internals.FatalExitError(statusCode);","typeGuard":"static boolean isValidExitCode(int code) {\n    return code != 0;\n}","tryCatchPattern":"// FatalExitError extends Error and is meant to terminate the JVM;\n// it should propagate to the top-level handler, not be caught in library code.\n// If you must guard construction:\ntry {\n    throw new FatalExitError(statusCode);\n} catch (IllegalArgumentException e) {\n    // message: \"statusCode must not be 0\"\n    // replace statusCode 0 with a conventional non-zero success-like code or do not throw at all\n}","preventionTips":["Never construct FatalExitError from client application code — its Javadoc states only servers/CLI tools should use it","Reserve statusCode 0 for normal JVM exit; FatalExitError by definition signals abnormal termination","Validate any externally-supplied exit code (config/env) for != 0 before wrapping it","If you only need to signal success, return normally rather than throwing FatalExitError(0)"],"tags":["lifecycle","fatal-exit","server","validation","illegal-argument"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}