# Sometimes no objective\_bound info from an LP solve, by Gurobi

**URL:** <https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080>\
**Category:** Optimization (Mathematical)\
**Tags:** question, gurobi\
**Created:** [January 15, 2026, 2:44pm UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080 "2026-01-15T14:44:03Z")\
**Posts on this page:** 14\
**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:** [January 15, 2026, 2:44pm UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/1 "2026-01-15T14:44:03Z")

</div>

I solved an LP by Gurobi using

```julia-auto
Non-default parameters:
Method 6
Crossover 0
PDHGGPU 1

```

And here’s the result

```julia-auto
julia> model
A JuMP Model
├ mode: DIRECT
├ solver: Gurobi
├ objective_sense: MIN_SENSE
│ └ objective_function_type: JuMP.AffExpr
├ num_variables: 51762757
├ num_constraints: 130897631
│ ├ JuMP.VariableRef in MOI.GreaterThan{Float64}: 51759445
│ ├ JuMP.AffExpr in MOI.GreaterThan{Float64}: 13570000
│ ├ JuMP.VariableRef in MOI.LessThan{Float64}: 24619445
│ ├ JuMP.AffExpr in MOI.LessThan{Float64}: 40715428
│ └ JuMP.AffExpr in MOI.EqualTo{Float64}: 233313
└ Names registered in the model: none

julia> JuMP.solution_summary(model)
solution_summary(; result = 1, verbose = false)
├ solver_name : Gurobi
├ Termination
│ ├ termination_status : OPTIMAL
│ ├ result_count : 1
│ └ raw_status : Model was solved to optimality (subject to tolerances), and an optimal solution is available.
├ Solution (result = 1)
│ ├ primal_status : FEASIBLE_POINT
│ ├ dual_status : FEASIBLE_POINT
│ ├ objective_value : 6.70482e+02
│ └ dual_objective_value : 6.70480e+02
└ Work counters
  ├ solve_time (sec) : 3.85499e+03
  ├ simplex_iterations : 0
  ├ barrier_iterations : 0
  └ node_count : 0

```

I fail to query the `objective_bound`. Why?

```julia-auto
julia> JuMP.objective_bound(model)
ERROR: MathOptInterface.GetAttributeNotAllowed{MathOptInterface.ObjectiveBound}:

## Cause

Getting attribute MathOptInterface.ObjectiveBound() cannot be performed

## Fixing this error

An `MOI.NotAllowedError` error occurs when you have tried to do something that
is not implemented by the solver.

The most common way to fix this error is to wrap the optimizer in a
`MOI.Utilities.CachingOptimizer`.

For example, if you are using `JuMP.Model` or `JuMP.set_optimizer`, do:

model = JuMP.Model(optimizer; with_cache_type = Float64)
model = JuMP.GenericModel{T}(optimizer; with_cache_type = T)
JuMP.set_optimizer(model, optimizer; with_cache_type = Float64)

Similarly, if you are using `MOI.instantiate`, do:

model = MOI.instantiate(optimizer; with_cache_type = Float64)

Stacktrace:
 [1] get(model::Gurobi.Optimizer, attr::MathOptInterface.ObjectiveBound)
   @ Gurobi ~/.julia/packages/Gurobi/Wo3Rk/src/MOI_wrapper/MOI_wrapper.jl:3344
 [2] _moi_get_result(model::Gurobi.Optimizer, args::MathOptInterface.ObjectiveBound)
   @ JuMP ~/.julia/packages/JuMP/N7h14/src/optimizer_interface.jl:1190
 [3] get(model::JuMP.Model, attr::MathOptInterface.ObjectiveBound)
   @ JuMP ~/.julia/packages/JuMP/N7h14/src/optimizer_interface.jl:1219
 [4] objective_bound(model::JuMP.Model)
   @ JuMP ~/.julia/packages/JuMP/N7h14/src/objective.jl:78
 [5] top-level scope
   @ REPL[35]:1

```

---

<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:** [January 15, 2026, 9:41pm UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/2 "2026-01-15T21:41:45Z")

</div>

Because Gurobi did not have one to return.

Querying the objective bound calls simply:

> <https://github.com/jump-dev/Gurobi.jl/blob/4c8e89375238f69b4afcacacec52dce44d7d9571/src/MOI_wrapper/MOI_wrapper.jl#L3323-L3332>

---

<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:** [January 15, 2026, 10:06pm UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/3 "2026-01-15T22:06:40Z")

</div>

I’m going to improve the error message: [Change error msg for GetAttributeNotAllowed when is\_set\_by\_optimize by odow · Pull Request #2910 · jump-dev/MathOptInterface.jl · GitHub](https://github.com/jump-dev/MathOptInterface.jl/pull/2910)

---

<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:** [January 16, 2026, 2:02am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/4 "2026-01-16T02:02:42Z")

</div>

> Because Gurobi did not have one to return.

It sometimes can indeed return one. While in this case it cannot. The behavior is somewhat nondeterministic. Don’t know the reason…

**Edit** : it appears that it depends on the `Crossover` parameter.

It appears to be safe to use this setting

```julia-auto
JuMP.set_attribute(model, "Crossover", 0);
JuMP.set_attribute(model, "Method", 2);

```

, but it’s unsafe to set `Crossover` to `0` if your `Method=6` (using PDHG)—in which case there is no `objective_bound` for an LP.

---

<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:** [January 18, 2026, 7:18am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/5 "2026-01-18T07:18:10Z")

</div>

These 3 APIs do refer to _distinct_ quantities:

```julia-auto
julia> map(f -> f(model), (
           JuMP.objective_value,
           JuMP.dual_objective_value,
           JuMP.objective_bound
       ))
(597.6414184756391, 597.6414184754293, 597.6414184752236)

```

Currently I have no idea where `dual_objective_value` can be used in daily applications. But the rest two, especially `objective_bound`, is necessary, e.g. in the Benders’ decomposition algorithm.

---

<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:** [January 18, 2026, 10:42pm UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/6 "2026-01-18T22:42:12Z")

</div>

The `dual_objective_value` shows up in feasibility cuts for Benders: [Benders decomposition · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/algorithms/benders_decomposition/#Feasibility-cuts)

I don’t think `objective_bound` is necessary in Benders.

---

<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:** [January 19, 2026, 1:35am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/7 "2026-01-19T01:35:24Z")

</div>

> [@odow](#):
>
> The `dual_objective_value` shows up in feasibility cuts for Benders: [Benders decomposition · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/algorithms/benders_decomposition/#Feasibility-cuts)

Having read that part, I think the usage there is weird—how can you retrieve any valid info when the termination status is `INFEASIBLE`? e.g.

```julia-auto
import JuMP, Gurobi
const GRB_ENV = Gurobi.Env();
const model = JuMP.direct_model(Gurobi.Optimizer(GRB_ENV));
const x0 = 3
JuMP.@variable(model, y <= 2)
JuMP.@variable(model, x == x0)
JuMP.@constraint(model, c, y >= x)
JuMP.optimize!(model)

julia> JuMP.solution_summary(model)
solution_summary(; result = 1, verbose = false)
├ solver_name : Gurobi
├ Termination
│ ├ termination_status : INFEASIBLE
│ ├ result_count : 0
│ └ raw_status : Model was proven to be infeasible.
├ Solution (result = 1)
│ ├ primal_status : NO_SOLUTION
│ └ dual_status : NO_SOLUTION

```

A modern method is to add slack variables to make the formulation always feasible, then we end up with `OPTIMAL` termination, and then we generate feasibility cuts, e.g.

```julia-auto
import JuMP, Gurobi
x = 1 # a trial solution decided in 1st-stage

m = JuMP.Model(Gurobi.Optimizer) # the 2nd-stage problem
JuMP.@variable(m, z) # copy variable of `x`
JuMP.fix(z, x)
JuMP.@variable(m, 0 <= y <= 1) # the original 2nd-stage variable
JuMP.@variable(m, 0 <= s <= 0) # an auxiliary slack variable in the 2nd-stage
JuMP.@constraint(m, s + 2z + y >= 4) # the original 2nd-stage constraint (modified with an `s`)
JuMP.optimize!(m)
JuMP.solution_summary(m) # INFEASIBLE + NO_SOLUTION + NO_SOLUTION 

# Go to solve the feasibility subproblem
JuMP.delete_upper_bound(s)
JuMP.@objective(m, Min, s)
JuMP.optimize!(m)
JuMP.solution_summary(m) # OPTIMAL
λ = JuMP.dual(JuMP.FixRef(z)) # -2.0
Cn = JuMP.objective_value(m) - (λ)x # 3.0
println("Our Feas. Cut is: dot($λ, x) + $Cn <= 0")

```

* * *

> [@odow](#):
>
> I don’t think `objective_bound` is necessary in Benders.

I think it’s essential. Benders decomposition, after all, is a _global optimization_ method, in which you keep both an upper bound and a lower (aka dual) bound. The term “upper bound” indeed should be more precisely described as “a objective value associated with a primal-side feasible solution”.

The _core_ reason that global optimizers like Gurobi are stronger than local optimizers like Ipopt is that they provide dual bound via the API `JuMP.objective_bound`. And this is essential in all _global optimization_ algorithms.

I’ve had a bunch of experience during the past several years studying these sorts of subjects. And I believe few people know about Benders decomposition better than I do. I don’t need to be modest on this particular field.

---

<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:** [January 19, 2026, 1:42am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/8 "2026-01-19T01:42:03Z")

</div>

> [@WalterMadelim](#):
>
> how can you retrieve any valid info when the termination status is `INFEASIBLE`

The dual\_status is `INFEASIBLITY_CERTIFICATE`. I’ll update the docs to make this clearer.

(This is yet another example where I need to say thank you. Your close reading of the documentation does lead to improvements 😄)

Edit: [[docs] clarify dual unbounded ray in Benders decomposition tutorial by odow · Pull Request #4109 · jump-dev/JuMP.jl · GitHub](https://github.com/jump-dev/JuMP.jl/pull/4109)

> I don’t think `objective_bound` is necessary in Benders.

I’ll be direct: `objective_bound` is **not** necessary for Benders. For example, we don’t use it in the tutorial [Benders decomposition · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/algorithms/benders_decomposition/). I don’t want to get into a discussion about this point.

---

<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:** [January 19, 2026, 1:50am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/9 "2026-01-19T01:50:55Z")

</div>

> [@odow](#):
>
> I’ll be direct: `objective_bound` is **not** necessary for Benders. For example, we don’t use it in the tutorial [Benders decomposition · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/algorithms/benders_decomposition/). I don’t want to get into a discussion about this point.

Trust me. Using `objective_value` in deriving the lower bound is _wrong_.

I’ll open a [PR](https://github.com/jump-dev/JuMP.jl/pull/4110#issue-3827681156) to revise that doc.

* * *

 ![image](https://global.discourse-cdn.com/julialang/original/3X/e/9/e94d11e544ae089b8ed526e429ee7d7d28e2b6da.png)

It doesn’t make sense to look at the `objective_value` of `model`, which is the master problem. The master problem is merely a surrogate. It only make sense to check the `objective_bound` of it. (I didn’t put images on Github, where it cannot be rendered decently).

After solving the master problem (even if not to `OPTIMAL`, i.e. suboptimally), we need to:

1. at the primal side, retrieve the best feasible solution of the 1st-stage decision variable
2. retrieve its `objective_bound`, which is a valid global lower bound, i.e. the one used in the Benders algorithm’s gap calculation.

These two **are** valid, and they **are the only** valid information that you can retrieve from the solvers.

* * *

Imagine now you solve the master problem with a local optimizer e.g. Ipopt.  
Then you must solve the master problem to GLOBAL OPTIMALITY and then retrieve the `objective_value`, since only at global optimality we have `objective_value(master) == objective_bound(master)`.

But you’re using Ipopt—the global optimality is never ensured. Therefore **you simply cannot use Ipopt to solve the Benders’ master problem**. Because by using Ipopt you cannot derive a valid lower bound in the Benders’ algorithm.

* * *

The correct way is to use a global optimizer, e.g. Gurobi, to solve the Benders’ master problem. And more importantly: you even do not need to solve the master problem (mixed-integer or not) to global optimality. Since the lower bound secured from `objective_bound` **is always valid**. And if the 1st-stage decision is feasible, the primal side solutions are also valid. In this manner you maintain **both primal and dual side validity**.

---

<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:** [January 19, 2026, 2:33am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/10 "2026-01-19T02:33:40Z")

</div>

Some other comments about the Bender Decomposition algorithm design:

- Initially the master problem is unbounded below, in literatures people often simple add a `θ >= -SOME_BIG_M` artificial constraint. Actually in practical applications, e.g. in 2SSP, this is not necessary. Because we can initially add a round of disaggregated cuts to ensure a finite initial bound.
- In practical applications we don’t need to adopt the gap shrinking as a termination criterion, since the upper bound calculation might be nontrivial. Actually we only need to monitor the ascending progress of the lower bound. And we can terminate once we are not able to add more violating cuts.
- A lot of literature study “stabilization techniques” of the master problem’s solution acquisition, e.g. proximal bundle method (I think Miles Lubin knows about this). I was quite obscured by these stuff when I entered this subject several years ago. But now I tend to believe that we don’t need these techniques at all—the naive cutting plane method already works well—provided you make proper use of multithreaded async programming—which we can immediately try out in the julia language.

---

<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:** [January 19, 2026, 2:45am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/11 "2026-01-19T02:45:44Z")

</div>

Since I’m curious. Let me directly @miles.lubin

---

<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:** [January 19, 2026, 2:56am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/12 "2026-01-19T02:56:46Z")

</div>

I replied to your PR: [Please using `objective_bound` in deriving the lower bound in Benders by WalterMadelim · Pull Request #4110 · jump-dev/JuMP.jl · GitHub](https://github.com/jump-dev/JuMP.jl/pull/4110)

I’m not going to reply any further on this thread.

---

<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:** [January 28, 2026, 2:56pm UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/13 "2026-01-28T14:56:56Z")

</div>

Last time in Github you wondered

> What MIP solver returns LOCALLY\_SOLVED?

It’s interesting that today I find Gurobi solves a master LP to `LOCALLY_SOLVED`, at a relatively mature stage of Benders Decomposition. I asked ChatGPT, which says it’s normal.

> **Details**
>
> ```julia-auto
> julia> JuMP.termination_status(mst)
> LOCALLY_SOLVED::TerminationStatusCode = 4
> 
> julia> JuMP.set_attribute(mst, "OutputFlag", 1)
> Set parameter OutputFlag to value 1
> 
> julia> JuMP.optimize!(mst)
> Gurobi Optimizer version 13.0.0 build v13.0.0rc1 (linux64gpu - "Debian GNU/Linux 12 (bookworm)")
> 
> CPU model: AMD EPYC 7763 64-Core Processor, instruction set [SSE2|AVX|AVX2]
> Thread count: 128 physical cores, 256 logical processors, using up to 1 threads
> 
> GPU model: NVIDIA RTX A6000, CUDA compute version 8.6, NVIDIA driver compatible with CUDA version 12
> 
> Non-default parameters:
> Method 2
> Crossover 0
> Threads 1
> 
> Optimize a model with 10668 rows, 14165 columns and 344764 nonzeros (Min)
> Model fingerprint: 0x9d492ba4
> Model has 9433 linear objective coefficients
> Coefficient statistics:
> Matrix range [1e-13, 9e+00]
> Objective range [1e-01, 2e+00]
> Bounds range [2e-02, 9e+00]
> RHS range [1e-01, 3e+03]
> Presolve removed 4333 rows and 7318 columns
> Presolve time: 0.13s
> Presolved: 6335 rows, 6847 columns, 332349 nonzeros
> Ordering time: 0.07s
> 
> Barrier statistics:
> AA' NZ : 7.819e+05
> Factor NZ : 1.910e+06 (roughly 20 MB of memory)
> Factor Ops : 7.547e+08 (less than 1 second per iteration)
> Threads : 1
> 
> Objective Residual
> Iter Primal Dual Primal Dual Compl Time
> 0 3.72977919e+05 -5.41621094e+03 4.64e+04 5.15e-03 1.13e+02 0s
> 1 1.45282171e+05 -1.06275556e+04 1.80e+04 3.45e-01 4.42e+01 1s
> 2 3.30605433e+04 -1.15471084e+04 4.03e+03 4.30e-02 1.03e+01 1s
> 3 7.99273001e+03 -9.59867649e+03 9.08e+02 1.03e-02 2.64e+00 1s
> 4 2.70680467e+03 -5.83032079e+03 2.47e+02 5.50e-15 8.18e-01 1s
> 5 1.20557076e+03 -2.25421523e+03 2.95e+01 4.27e-15 2.08e-01 1s
> 6 9.52519974e+02 1.50838346e+02 4.95e+00 3.94e-15 4.29e-02 1s
> 7 7.87952666e+02 6.22975623e+02 3.06e-01 2.89e-15 8.67e-03 1s
> 8 7.36375718e+02 7.18202368e+02 1.23e-02 1.78e-15 9.57e-04 1s
> 9 7.27549652e+02 7.25838522e+02 5.01e-04 1.78e-15 9.02e-05 1s
> 10 7.26804299e+02 7.26489268e+02 7.41e-05 2.66e-15 1.66e-05 2s
> 11 7.26714214e+02 7.26542085e+02 3.72e-05 1.78e-15 9.08e-06 2s
> 12 7.26633637e+02 7.26605198e+02 4.93e-06 2.22e-15 1.50e-06 2s
> 13 7.26622687e+02 7.26619123e+02 5.63e-07 1.78e-15 1.88e-07 2s
> 14 7.26620850e+02 7.26620608e+02 4.15e-08 1.78e-15 1.28e-08 2s
> 15 7.26620844e+02 7.26620609e+02 6.64e-06 1.78e-15 1.27e-08 2s
> 16 7.26620844e+02 7.26620611e+02 7.17e-06 1.78e-15 1.25e-08 2s
> 17 7.26620841e+02 7.26620617e+02 1.63e-05 1.78e-15 1.19e-08 3s
> 18 7.26620842e+02 7.26620619e+02 2.08e-05 1.78e-15 1.18e-08 3s
> 19 7.26620842e+02 7.26620619e+02 2.07e-05 1.78e-15 1.18e-08 3s
> 20 7.26620832e+02 7.26620665e+02 2.46e-05 2.22e-15 8.75e-09 3s
> 21 7.26620815e+02 7.26620673e+02 2.40e-05 1.78e-15 8.01e-09 3s
> 22 7.26620794e+02 7.26620687e+02 2.86e-05 1.78e-15 6.86e-09 3s
> 23 7.26620794e+02 7.26620689e+02 2.73e-05 1.78e-15 6.72e-09 3s
> 24 7.26620791e+02 7.26620694e+02 2.61e-05 1.78e-15 6.29e-09 3s
> 25 7.26620792e+02 7.26620699e+02 2.48e-05 1.94e-15 5.98e-09 3s
> 26 7.26620786e+02 7.26620700e+02 2.55e-05 1.78e-15 5.90e-09 4s
> 27 7.26620783e+02 7.26620700e+02 2.44e-05 2.44e-15 5.90e-09 4s
> 28 7.26620724e+02 7.26620706e+02 4.59e-05 1.33e-15 5.29e-09 4s
> 29 7.26620725e+02 7.26620706e+02 4.62e-05 2.66e-15 5.24e-09 4s
> 30 7.26620716e+02 7.26620712e+02 4.27e-05 1.78e-15 4.00e-09 4s
> 31 7.26620682e+02 7.26620713e+02 5.14e-05 3.47e-15 3.63e-09 4s
> 32 7.26620576e+02 7.26620714e+02 1.20e-04 2.66e-15 3.49e-09 4s
> 33 7.26620601e+02 7.26620726e+02 1.09e-04 1.78e-15 2.73e-09 4s
> 34 7.26620600e+02 7.26620726e+02 1.08e-04 1.78e-15 2.73e-09 5s
> 35 7.26620612e+02 7.26620726e+02 9.84e-05 1.78e-15 2.59e-09 5s
> 36 7.26620631e+02 7.26620726e+02 9.95e-05 2.47e-15 2.58e-09 5s
> 37 7.26620630e+02 7.26620727e+02 9.94e-05 2.00e-15 2.56e-09 5s
> 38 7.26620651e+02 7.26620733e+02 8.81e-05 1.78e-15 2.08e-09 5s
> 39 7.26620643e+02 7.26620733e+02 8.85e-05 1.78e-15 2.07e-09 5s
> 40 7.26620667e+02 7.26620735e+02 7.43e-05 3.55e-15 1.82e-09 5s
> 41 7.26620678e+02 7.26620738e+02 7.02e-05 2.45e-15 1.65e-09 5s
> 42 7.26620706e+02 7.26620738e+02 6.24e-05 1.78e-15 1.51e-09 5s
> 43 7.26620675e+02 7.26620740e+02 1.15e-04 1.78e-15 1.40e-09 6s
> 44 7.26620692e+02 7.26620742e+02 9.52e-05 2.22e-15 1.18e-09 6s
> 45 7.26620753e+02 7.26620745e+02 7.57e-05 1.78e-15 5.62e-10 6s
> 46 7.26620753e+02 7.26620746e+02 7.73e-05 1.78e-15 4.96e-10 6s
> 47 7.26620741e+02 7.26620746e+02 7.46e-05 1.78e-15 4.71e-10 6s
> 48 7.26620703e+02 7.26620747e+02 6.17e-05 1.78e-15 4.05e-10 6s
> 49 7.26620709e+02 7.26620747e+02 6.02e-05 3.85e-15 3.86e-10 6s
> 50 7.26620693e+02 7.26620748e+02 5.35e-05 2.66e-15 3.59e-10 6s
> 51 7.26620625e+02 7.26620748e+02 5.66e-05 1.78e-15 3.38e-10 7s
> 52 7.26620624e+02 7.26620748e+02 5.66e-05 2.79e-15 3.37e-10 7s
> 53 7.26620639e+02 7.26620748e+02 6.44e-05 1.78e-15 3.31e-10 7s
> 54 7.26620639e+02 7.26620748e+02 6.48e-05 3.61e-15 3.33e-10 7s
> 55 7.26620810e+02 7.26620749e+02 7.71e-05 1.52e-15 3.05e-10 7s
> 56 7.26620905e+02 7.26620749e+02 1.42e-04 3.73e-15 2.90e-10 7s
> 57 7.26620880e+02 7.26620750e+02 1.06e-04 3.75e-15 1.81e-10 7s
> 58 7.26620873e+02 7.26620750e+02 1.02e-04 4.22e-15 1.81e-10 7s
> 59 7.26620833e+02 7.26620751e+02 7.49e-05 3.32e-15 1.78e-10 8s
> 60 7.26620827e+02 7.26620750e+02 8.62e-05 3.61e-15 1.76e-10 8s
> 61 7.26620743e+02 7.26620750e+02 1.02e-04 6.22e-15 1.76e-10 8s
> 62 7.26620729e+02 7.26620750e+02 1.12e-04 5.38e-15 1.76e-10 8s
> 63 7.26620730e+02 7.26620751e+02 1.10e-04 4.14e-15 1.63e-10 8s
> 64 7.26620728e+02 7.26620751e+02 1.10e-04 3.40e-15 1.62e-10 8s
> 65 7.26620729e+02 7.26620751e+02 1.10e-04 8.84e-15 1.57e-10 8s
> 66 7.26620742e+02 7.26620751e+02 9.69e-05 9.83e-15 1.56e-10 8s
> 67 7.26620742e+02 7.26620751e+02 9.54e-05 1.82e-14 1.56e-10 8s
> 68 7.26620744e+02 7.26620751e+02 9.45e-05 1.86e-14 1.44e-10 9s
> 69 7.26620704e+02 7.26620751e+02 1.28e-04 1.60e-14 1.42e-10 9s
> 70 7.26620682e+02 7.26620751e+02 1.03e-04 1.49e-14 1.36e-10 9s
> 71 7.26620696e+02 7.26620752e+02 1.12e-04 5.14e-15 1.11e-10 9s
> 72 7.26620756e+02 7.26620752e+02 8.07e-05 2.02e-14 1.10e-10 9s
> 73 7.26620829e+02 7.26620752e+02 8.14e-05 1.91e-14 1.10e-10 9s
> 74 7.26620979e+02 7.26620752e+02 1.59e-04 1.32e-14 1.02e-10 9s
> 75 7.26620981e+02 7.26620752e+02 1.55e-04 1.56e-14 8.85e-11 9s
> 
> Barrier performed 75 iterations in 9.44 seconds (14.33 work units)
> Sub-optimal termination - objective 7.26620844e+02
> 
> User-callback calls 1030, time in user-callback 0.00 sec
> 
> julia> JuMP.solution_summary(mst)
> solution_summary(; result = 1, verbose = false)
> ├ solver_name : Gurobi
> ├ Termination
> │ ├ termination_status : LOCALLY_SOLVED
> │ ├ result_count : 1
> │ ├ raw_status : Unable to satisfy optimality tolerances; a sub-optimal solution is available.
> │ └ objective_bound : 7.26621e+02
> ├ Solution (result = 1)
> │ ├ primal_status : UNKNOWN_RESULT_STATUS
> │ ├ dual_status : UNKNOWN_RESULT_STATUS
> │ ├ objective_value : 7.26621e+02
> │ └ dual_objective_value : 7.26621e+02
> └ Work counters
> ├ solve_time (sec) : 9.44116e+00
> ├ simplex_iterations : 0
> ├ barrier_iterations : 75
> └ node_count : 0
> 
> julia> mst
> A JuMP Model
> ├ mode: DIRECT
> ├ solver: Gurobi
> ├ objective_sense: MIN_SENSE
> │ └ objective_function_type: JuMP.AffExpr
> ├ num_variables: 14165
> ├ num_constraints: 29558
> │ ├ JuMP.VariableRef in MOI.GreaterThan{Float64}: 9445
> │ ├ JuMP.AffExpr in MOI.GreaterThan{Float64}: 3
> │ ├ JuMP.VariableRef in MOI.LessThan{Float64}: 9445
> │ ├ JuMP.AffExpr in MOI.LessThan{Float64}: 5947
> │ └ JuMP.AffExpr in MOI.EqualTo{Float64}: 4718
> └ Names registered in the model: none
> 
> ```

---

<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:** [January 29, 2026, 7:35am UTC](https://discourse.julialang.org/t/sometimes-no-objective-bound-info-from-an-lp-solve-by-gurobi/135080/14 "2026-01-29T07:35:35Z")

</div>

> [@WalterMadelim](#):
>
> What MIP solver returns LOCALLY\_SOLVED?

I meant when solving a MIP. Yes, you can get LOCALLY\_SOLVED for an LP.
