numpy/numpy · critical

STOP %s statement executed

Error message

STOP %s statement executed

What it means

s_stop in numpy/linalg/lapack_lite/f2c.c:743 is the f2c runtime stub backing Fortran's `STOP [msg]` statement for the C-translated LAPACK used by numpy.linalg. It prints `STOP <msg> statement executed` to stderr and then calls exit(0) (line 758), terminating the entire Python process. There is no exception to catch — the interpreter is simply replaced — and because the exit code is 0 the failure looks like a clean exit, masking the crash. In shipped lapack_lite this path is not normally reachable because LAPACK reports errors through XERBLA rather than STOP, so encountering it usually indicates an internal LAPACK branch, a custom/patched lapack_lite, or other f2c-compiled Fortran linked into the interpreter executing a STOP.

Source

Thrown at numpy/linalg/lapack_lite/f2c.c:750

#undef abs
#undef min
#undef max
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
extern "C" {
#endif
void f_exit(void);

int s_stop(char *s, ftnlen n)
#endif
{
int i;

if(n > 0)
	{
	fprintf(stderr, "STOP ");
	for(i = 0; i<n ; ++i)
		putc(*s++, stderr);
	fprintf(stderr, " statement executed\n");
	}
#ifdef NO_ONEXIT
f_exit();
#endif
exit(0);

/* We cannot avoid (useless) compiler diagnostics here:		*/
/* some compilers complain if there is no return statement,	*/
/* and others complain that this one cannot be reached.		*/

return 0; /* NOT REACHED */
}
#ifdef __cplusplus
}
#endif

View on GitHub (pinned to e117b3ca4e)

Solutions

  1. Validate and sanitize inputs (shape, squareness, dtype, finiteness, contiguity) before the numpy.linalg call so the LAPACK routine never reaches an abnormal branch.
  2. Reproduce the call in a throwaway child process to confirm which invocation triggers the STOP — the parent dies with exit code 0, so the only way to keep working is process isolation.
  3. If a plain numpy.linalg call on well-formed input reproduces it, file a NumPy bug with a minimal reproducer; reaching STOP from numpy.linalg indicates a lapack_lite issue.
  4. Avoid linking custom f2c-compiled Fortran that uses STOP into the interpreter — replace STOP with XERBLA / error-return paths.

Example fix

# before — unvalidated input can drive LAPACK into a STOP branch,
# killing the whole process with exit(0) and no traceback
v = np.linalg.eigvals(M)

# after — sanitize inputs and isolate the call in a subprocess so a
# STOP/exit(0) cannot take down the main process
import numpy as np, subprocess, sys, json
M = np.ascontiguousarray(M, dtype=np.float64)
assert M.ndim == 2 and M.shape[0] == M.shape[1], "M must be 2-D square"
assert np.isfinite(M).all(), "M must not contain NaN/Inf"
prog = ("import numpy as np, json, sys;"
        "r=np.linalg.eigvals(np.array(json.loads(sys.stdin.read())));"
        "sys.stdout.write(json.dumps(r.tolist()))")
p = subprocess.run([sys.executable, "-c", prog],
                   input=json.dumps(M.tolist()), capture_output=True, text=True)
if p.returncode != 0 or "STOP" in p.stderr:
    raise RuntimeError("LAPACK STOP killed subprocess: " + p.stderr)
v = np.array(json.loads(p.stdout))
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def validate_linalg_matrix(M, square=True):
    """Sanitize a matrix for numpy.linalg so LAPACK never hits an abnormal
    (STOP) branch. Returns a contiguous float array."""
    M = np.ascontiguousarray(M)
    if square:
        if M.ndim != 2 or M.shape[0] != M.shape[1]:
            raise ValueError(f"expected 2-D square matrix, got shape {M.shape}")
    if M.dtype.kind != "f":
        M = M.astype(np.float64)
    if not np.isfinite(M).all():
        raise ValueError("input contains NaN or Inf")
    return M

Type guard

import numpy as np

def is_valid_matrix(M, square=True):
    ok = isinstance(M, np.ndarray) and M.ndim == 2 and M.dtype.kind == "f" and np.isfinite(M).all()
    if square:
        ok = ok and M.shape[0] == M.shape[1]
    return ok

Try / catch

# exit(0) inside the C extension CANNOT be caught by try/except —
# the whole interpreter dies. The only robust pattern is subprocess
# isolation, treating any 'STOP ... statement executed' or exit 0 as failure.
import subprocess, sys, json

def safe_linalg(fn_code, M):
    """fn_code is a snippet that reads JSON M on stdin and writes JSON result."""
    p = subprocess.run([sys.executable, "-c", fn_code],
                       input=json.dumps(np.asarray(M).tolist()),
                       capture_output=True, text=True)
    if p.returncode != 0 or "STOP" in p.stderr:
        raise RuntimeError("LAPACK STOP killed subprocess (rc=%d): %s"
                           % (p.returncode, p.stderr))
    return json.loads(p.stdout)

Prevention

When it happens

Trigger: A Fortran routine translated via f2c executes a STOP statement. Concretely: a numpy.linalg call routes into lapack_lite and hits an abnormal/internal branch that STOPs; or user-supplied f2c-compiled Fortran linked into the process runs a STOP; or a custom/modified lapack_lite build introduces a STOP reachable on certain inputs.

Common situations: Passing pathological matrix inputs (degenerate shapes, extreme scaling, NaN/Inf) that drive a LAPACK routine into an unexpected branch; using a custom or patched lapack_lite build; linking application f2c-compiled Fortran that uses STOP for error handling; subtle differences across numpy/lapack_lite versions or build configurations.

Related errors


AI-assisted analysis of numpy/numpy@e117b3ca4e (2026-08-07). Data as JSON: /api/errors/f387cc55392c3560. Report an issue: GitHub.