scipy minimize error: success False, precision loss, maxiter (tested)

scipy.optimize.minimize usually does not raise when it fails: it returns success=False with a message such as "Maximum number of iterations has been exceeded" or "Desired error not necessarily achieved due to precision loss". Below, each message is reproduced, with the fix that made it converge.

1. success=False: read message and status, not just x

scipy.optimize.minimize almost never raises when the optimizer fails. It returns an OptimizeResult with success=False, a numeric status and a message. b1.py triggers the most common ones:

import numpy as np
from scipy.optimize import minimize, rosen

# minimize() rarely raises: it returns success=False plus a message
r = minimize(rosen, np.zeros(5), method="BFGS", options={"maxiter": 10})
print("1:", r.success, r.status, "|", r.message, "| nit", r.nit)
r = minimize(rosen, np.zeros(5), method="BFGS")
print("2:", r.success, r.status, "|", r.message, "| nit", r.nit)

# non-smooth objective: BFGS lands on the answer but reports failure
def f_abs(x):
    return abs(x[0] - 2) + abs(x[1] + 1)
r = minimize(f_abs, [0.0, 0.0], method="BFGS")
print("3:", r.success, r.status, "|", r.message, "| x", np.round(r.x, 4))
r = minimize(f_abs, [0.0, 0.0], method="Nelder-Mead")
print("4:", r.success, r.status, "|", r.message, "| x", np.round(r.x, 4))

# constraints that cannot all hold (x >= 2 and x <= 1)
cons = [{"type": "ineq", "fun": lambda x: x[0] - 2},
        {"type": "ineq", "fun": lambda x: 1 - x[0]}]
r = minimize(lambda x: x[0]**2, [0.0], method="SLSQP", constraints=cons)
print("5:", r.success, r.status, "|", r.message)

Output (SciPy 1.18.1, NumPy 2.5.4, Python 3.13.5):

1: False 1 | Maximum number of iterations has been exceeded. | nit 10
2: True 0 | Optimization terminated successfully. | nit 40
3: False 2 | Desired error not necessarily achieved due to precision loss. | x [ 2. -1.]
4: True 0 | Optimization terminated successfully. | x [ 2. -1.]
5: False 8 | Positive directional derivative for linesearch

2. Errors that do raise, and the NaN case

import numpy as np
from scipy.optimize import minimize

def show(label, fn):
    try:
        r = fn()
        print(label, "->", r.success, "|", r.message)
    except Exception as e:
        print(label, "->", type(e).__name__ + ":", e)

# objective returns an array instead of a scalar
show("A array", lambda: minimize(lambda x: (x - 1)**2, [0.0, 0.0]))
# extra arguments not passed via args=
def f(x, a):
    return ((x - a)**2).sum()
show("B no args", lambda: minimize(f, [0.0]))
show("C args", lambda: minimize(f, [0.0], args=(4.0,)))
# 2-D x0
show("D 2-D x0", lambda: minimize(lambda x: (x**2).sum(), np.zeros((2, 2))))
# objective goes NaN outside its domain
def g(x):
    return np.sqrt(x[0]) + x[0]
show("E nan", lambda: minimize(g, [1.0]))
show("F bounds", lambda: minimize(g, [1.0], bounds=[(0, None)]))

Output:

A array -> ValueError: The user-provided objective function must return a scalar value.
B no args -> TypeError: f() missing 1 required positional argument: 'a'
C args -> True | Optimization terminated successfully.
D 2-D x0 -> ValueError: 'x0' must only have one dimension.
/tmp/sm408/b2.py:22: RuntimeWarning: invalid value encountered in sqrt
  return np.sqrt(x[0]) + x[0]
/tmp/sm408/b2.py:22: RuntimeWarning: invalid value encountered in sqrt
  return np.sqrt(x[0]) + x[0]
/tmp/sm408/b2.py:22: RuntimeWarning: invalid value encountered in sqrt
  return np.sqrt(x[0]) + x[0]
E nan -> False | Desired error not necessarily achieved due to precision loss.
F bounds -> True | CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL

3. Checklist

  1. Print r.success, r.status, r.message, r.nit.
  2. Iteration limit: raise maxiter, or rescale variables so they are of similar size.
  3. Precision loss: look for NaN/inf (run with np.seterr(all="raise") to find where), non-smooth terms, or an inaccurate gradient; add bounds or switch method.
  4. SLSQP status 8 or similar with constraints: test the constraints alone at a point you know is feasible.

Related: NumPy floating point errors and isclose, numpy polyfit RankWarning.

Frequently asked questions

Why does scipy minimize return success False?

The optimizer stopped without meeting its tolerance: iteration limit, precision loss from NaN or non-smooth objectives, or infeasible constraints. Read r.message and r.status.

What does "Desired error not necessarily achieved due to precision loss" mean?

BFGS could not make progress along its line search, usually because the objective returned NaN, is not smooth, or the gradient is inaccurate.

How do I fix "The user-provided objective function must return a scalar value"?

Make the objective return one number, for example by summing squared residuals.

Written with AI assistance. Measured on 2026-10-23 with SciPy 1.18.1, NumPy 2.5.4 and Python 3.13.5 on Linux. Scripts ran verbatim and the output was pasted unedited. PlainTables is our extension; SciPy is free.