apache/kafka · error · IllegalArgumentException

statusCode must not be 0

Error message

statusCode must not be 0

What it means

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.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/internals/FatalExitError.java:36

import org.apache.kafka.common.utils.internals.Exit;

/**
 * An error that indicates the need to exit the JVM process. This should only be used by the server or command-line
 * tools. Clients should never shutdown the JVM process.
 *
 * This exception is expected to be caught at the highest level of the thread so that no shared lock is held by
 * the thread when it calls {@link Exit#exit(int)}.
 */
public class FatalExitError extends Error {

    private static final long serialVersionUID = 1L;

    private final int statusCode;

    public FatalExitError(int statusCode) {
        if (statusCode == 0)
            throw new IllegalArgumentException("statusCode must not be 0");
        this.statusCode = statusCode;
    }

    public FatalExitError() {
        this(1);
    }

    public int statusCode() {
        return statusCode;
    }
}

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Pass a non-zero status (the no-arg constructor FatalExitError() defaults to 1).
  2. If the status originates from config/input, validate it is non-zero before constructing FatalExitError, or pick a sensible non-zero default.
  3. Reconsider whether FatalExitError is the right vehicle if you genuinely want a clean (status 0) shutdown; use a normal return / graceful close path instead.
  4. In tests, exclude 0 from parameterized exit-code matrices or assert that IllegalArgumentException is thrown for it.

Example fix

// before
throw new FatalExitError(exitCode);   // exitCode may be 0

// after
if (exitCode == 0) throw new IllegalArgumentException("exitCode must be non-zero");
throw new FatalExitError(exitCode);
Defensive patterns

Strategy: validation

Validate before calling

int statusCode = ...;
if (statusCode == 0) {
    throw new IllegalArgumentException("FatalExitError requires a non-zero statusCode (use a different signal for success)");
}
new org.apache.kafka.common.internals.FatalExitError(statusCode);

Type guard

static boolean isValidExitCode(int code) {
    return code != 0;
}

Try / catch

// FatalExitError extends Error and is meant to terminate the JVM;
// it should propagate to the top-level handler, not be caught in library code.
// If you must guard construction:
try {
    throw new FatalExitError(statusCode);
} catch (IllegalArgumentException e) {
    // message: "statusCode must not be 0"
    // replace statusCode 0 with a conventional non-zero success-like code or do not throw at all
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/a66aa3728e8ccab9.json. Report an issue: GitHub.