# Gurobi fails to properly report an ERROR, when NonConvex is 0

**URL:** <https://discourse.julialang.org/t/gurobi-fails-to-properly-report-an-error-when-nonconvex-is-0/130932>\
**Category:** Optimization (Mathematical)\
**Tags:** question, gurobi\
**Created:** [July 22, 2025, 4:41am UTC](https://discourse.julialang.org/t/gurobi-fails-to-properly-report-an-error-when-nonconvex-is-0/130932 "2025-07-22T04:41:07Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [July 22, 2025, 4:41am UTC](https://discourse.julialang.org/t/gurobi-fails-to-properly-report-an-error-when-nonconvex-is-0/130932/1 "2025-07-22T04:41:07Z")

</div>

I discover this behavior of Gurobi, which I think is not exactly expected.  
According to Gurobi’s [doc](https://docs.gurobi.com/projects/optimizer/en/current/reference/parameters.html#nonconvex), if `NonConvex` is set to `0`, then Gurobi should ERROR when a nonconvex quadratic constraint is present.

```julia
julia> import JuMP, Gurobi; GRB_ENV = Gurobi.Env();

julia> using LinearAlgebra

julia> A = [0.6500000000000001 0.4330127018922193; 0.4330127018922193 0.24999999999999994];

julia> eigen(A)
Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}}
values:
2-element Vector{Float64}:
 -0.02696960070847279
  0.9269696007084729

julia> model = JuMP.Model(() -> Gurobi.Optimizer(GRB_ENV));

julia> JuMP.@variable(model, x[1:2]);

julia> JuMP.@variable(model, z);

julia> JuMP.set_attribute(model, "Nonconvex", 0) # I explicitly set this
Set parameter NonConvex to value 0

julia> JuMP.@constraint(model, z ≥ x' * A * x) # nonconvex
-0.6500000000000001 x[1]² - 0.8660254037844386 x[2]*x[1] - 0.24999999999999994 x[2]² + z >= 0

julia> JuMP.optimize!(model) # 🔴 I think Gurobi should ERROR here, but it didn't
Set parameter NonConvex to value 0
Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (win64 - Windows 11.0 (26100.2))

CPU model: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz, instruction set [SSE2|AVX|AVX2|AVX512]
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Non-default parameters:
NonConvex 0

Optimize a model with 0 rows, 3 columns and 0 nonzeros
Model fingerprint: 0x36f7eae6
Model has 1 quadratic constraint
Coefficient statistics:
  Matrix range [0e+00, 0e+00]
  QMatrix range [2e-01, 9e-01]
  QLMatrix range [1e+00, 1e+00]
  Objective range [0e+00, 0e+00]
  Bounds range [0e+00, 0e+00]
  RHS range [0e+00, 0e+00]
Presolve removed 0 rows and 3 columns
Presolve time: 0.00s
Presolve: All rows and columns removed

Barrier solved model in 0 iterations and 0.00 seconds (0.00 work units)
Optimal objective 0.00000000e+00

User-callback calls 28, time in user-callback 0.00 sec

julia> JuMP.@objective(model, Min, z);

julia> JuMP.optimize!(model) # By comparison, this is expected
Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (win64 - Windows 11.0 (26100.2))

CPU model: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz, instruction set [SSE2|AVX|AVX2|AVX512]
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Non-default parameters:
NonConvex 0

Optimize a model with 0 rows, 3 columns and 0 nonzeros
Model fingerprint: 0x4893b5bf
Model has 1 quadratic constraint
Coefficient statistics:
  Matrix range [0e+00, 0e+00]
  QMatrix range [2e-01, 9e-01]
  QLMatrix range [1e+00, 1e+00]
  Objective range [1e+00, 1e+00]
  Bounds range [0e+00, 0e+00]
  RHS range [0e+00, 0e+00]

User-callback calls 19, time in user-callback 0.00 sec
ERROR: Gurobi Error 10020: Objective Q not PSD (diagonal adjustment of 7.7e-02 would be required). Set NonConvex parameter to -1 or 2 to solve model.

```

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [July 22, 2025, 4:51am UTC](https://discourse.julialang.org/t/gurobi-fails-to-properly-report-an-error-when-nonconvex-is-0/130932/2 "2025-07-22T04:51:57Z")

</div>

Here is a sharper example

```julia
julia> model = JuMP.Model(() -> Gurobi.Optimizer(GRB_ENV))

julia> JuMP.@variable(model, x)

julia> JuMP.@variable(model, y)

julia> JuMP.set_attribute(model, "NonConvex", 0)

julia> JuMP.@constraint(model, y ≤ x^2)

julia> JuMP.optimize!(model) # 🔴 No ERROR can be seen
Set parameter NonConvex to value 0
Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (win64 - Windows 11.0 (26100.2))

CPU model: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz, instruction set [SSE2|AVX|AVX2|AVX512]
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Non-default parameters:
NonConvex 0

Optimize a model with 0 rows, 2 columns and 0 nonzeros
Model fingerprint: 0x27adffff
Model has 1 quadratic constraint
Coefficient statistics:
  Matrix range [0e+00, 0e+00]
  QMatrix range [1e+00, 1e+00]
  QLMatrix range [1e+00, 1e+00]
  Objective range [0e+00, 0e+00]
  Bounds range [0e+00, 0e+00]
  RHS range [0e+00, 0e+00]
Presolve removed 0 rows and 2 columns
Presolve time: 0.00s
Presolve: All rows and columns removed

Barrier solved model in 0 iterations and 0.00 seconds (0.00 work units)
Optimal objective 0.00000000e+00

User-callback calls 28, time in user-callback 0.00 sec

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [July 22, 2025, 10:02pm UTC](https://discourse.julialang.org/t/gurobi-fails-to-properly-report-an-error-when-nonconvex-is-0/130932/3 "2025-07-22T22:02:23Z")

</div>

Note

> `Presolve: All rows and columns removed`

I assume Gurobi does not error because it can solve the problem.

---

<div class="post-metadata">

**Author:** ![cvanaret](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cvanaret/32/11594_2.png) [@cvanaret](https://discourse.julialang.org/u/cvanaret)\
**Post date:** [July 26, 2025, 6:04pm UTC](https://discourse.julialang.org/t/gurobi-fails-to-properly-report-an-error-when-nonconvex-is-0/130932/4 "2025-07-26T18:04:18Z")

</div>

You have free variables and no objective, so I’m assuming Gurobi just drops the nonconvex constraint altogether during presolve.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [July 26, 2025, 11:44pm UTC](https://discourse.julialang.org/t/gurobi-fails-to-properly-report-an-error-when-nonconvex-is-0/130932/5 "2025-07-26T23:44:08Z")

</div>

Have a look at this example, in which Gurobi properly throws ERROR

```julia
julia> model = JuMP.Model(() -> Gurobi.Optimizer(GRB_ENV));

julia> JuMP.@variable(model, x[1:2]); # free variable

julia> JuMP.@constraint(model, sum(x -> x^2, x) ≥ 2); # nonconvex

julia> JuMP.set_attribute(model, "NonConvex", 0);

julia> JuMP.optimize!(model)
Set parameter NonConvex to value 0
Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (win64 - Windows 11.0 (26100.2))

CPU model: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz, instruction set [SSE2|AVX|AVX2|AVX512]
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Non-default parameters:
NonConvex 0

Optimize a model with 0 rows, 2 columns and 0 nonzeros
Model fingerprint: 0x89cce529
Model has 1 quadratic constraint
Coefficient statistics:
  Matrix range [0e+00, 0e+00]
  QMatrix range [1e+00, 1e+00]
  Objective range [0e+00, 0e+00]
  Bounds range [0e+00, 0e+00]
  RHS range [0e+00, 0e+00]
  QRHS range [2e+00, 2e+00]

User-callback calls 19, time in user-callback 0.00 sec
ERROR: Gurobi Error 10020: Constraint Q not PSD (diagonal adjustment of 1.0e+00 would be required). Set NonConvex parameter to -1 or 2 to solve model.

```

> [@cvanaret](#):
>
> just drops the nonconvex constraint

He can drop it in order to infer that the model is feasible (thus OPTIMAL due to the absence of an objective).  
But he still need to cope with that nonconvex constraint—he needs to calculate a feasible point—he cannot randomly give me a solution like (x = 0, y = 1) (which violates my nonconvex constraint). At this phase I think Gurobi should ERROR.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [July 27, 2025, 3:15am UTC](https://discourse.julialang.org/t/gurobi-fails-to-properly-report-an-error-when-nonconvex-is-0/130932/6 "2025-07-27T03:15:45Z")

</div>

You’re thinking too much about the edge cases of Gurobi’s behavior. If you have a nonconvex model AND you set the nonconvex parameter to 0 AND it can be solved in presolve then gurobi will report optimal. If it cannot be presolved to optimality Gurobi will error. This behavior seems like it is intended and it is not a bug.
