Skip to content

cuOpt.jl MOI wrapper: unhandled 'Invalid argument' from GetPrimalSolution/GetDualSolution fails 36 conformance tests every nightly run #1832

Description

@ramakrishnap-nv

Summary

cuOpt.jl's MOI wrapper optimize! unconditionally calls cuOptGetPrimalSolution/cuOptGetDualSolution after solving, without checking termination status first. This throws an "Invalid argument" C-API error (rather than returning gracefully) whenever:

  • the problem was declared infeasible/unbounded (often at presolve, so no primal solution buffer exists), or
  • the problem has quadratic/second-order-cone constraints (duals are documented as not returned for these: "Dual variables for problems with quadratic constraints not returned.")

This causes the thirdparty jump (Julia MOI conformance) test step to fail on every nightly wheel-tests-cuopt job, across all GPU/driver/dependency combinations, while all Python test suites (LP/MILP/QP/routing/classification) pass cleanly.

Observed in

Nightly test.yaml run 33361623272 (main @ d3af87e3, 2026-08-31) — all wheel-tests-cuopt matrix jobs report thirdparty jump as a failed step, consistently: 1397 passed, 0 failed, 36 errored, 0 broken.

This is not a one-off: test.yaml has failed with this same 36 errored Julia MOI signature on nearly every nightly run since at least 2026-08-13 (3+ weeks), e.g. runs 33295253627, 33237039486, 33154333403, 33053460319, 32936929656, 32814253431.

Distinct from the previously-fixed #1485 (a Julia 1.12.x JIT SIGSEGV on MOI.delete for bridged SOC constraints) — that was a crash bug fixed via an exclude list; this is a separate, still-open error-handling gap in the wrapper's result-fetching path (no crash, just an unhandled C-API error surfaced as a Julia test error).

Example stack trace

test_conic_SecondOrderCone_negative_initial_bound: Error During Test at .../MathOptInterface/Test/Test.jl:264
  Got exception outside of a @test
  Invalid argument in cuOptGetDualSolution.
  Stacktrace:
    [1] error(s::String) @ Base ./error.jl:44
    [2] _check_ret(ret::Int32, msg::String) @ cuOpt .../cuOpt.jl/src/MOI_wrapper.jl:438
    [3] optimize!(model::cuOpt.Optimizer) @ cuOpt .../cuOpt.jl/src/MOI_wrapper.jl:1316
test_infeasible_MAX_SENSE: Error During Test at .../MathOptInterface/Test/Test.jl:264
  Got exception outside of a @test
  Invalid argument in cuOptGetPrimalSolution.
  Stacktrace:
    [1] error(s::String) @ Base ./error.jl:44
    [2] _check_ret(ret::Int32, msg::String) @ cuOpt .../cuOpt.jl/src/MOI_wrapper.jl:438
    [3] optimize!(model::cuOpt.Optimizer) @ cuOpt .../cuOpt.jl/src/MOI_wrapper.jl:1307

Affected tests (36, same set every night)

test_conic_SecondOrderCone_negative_initial_bound
test_conic_SecondOrderCone_negative_post_bound
test_conic_SecondOrderCone_nonnegative_initial_bound
test_constraint_ZeroOne_bounds_3
test_infeasible_affine_MAX_SENSE
test_infeasible_affine_MAX_SENSE_offset
test_infeasible_affine_MIN_SENSE
test_infeasible_affine_MIN_SENSE_offset
test_infeasible_MAX_SENSE
test_infeasible_MAX_SENSE_offset
test_infeasible_MIN_SENSE
test_infeasible_MIN_SENSE_offset
test_linear_DUAL_INFEASIBLE
test_linear_DUAL_INFEASIBLE_2
test_linear_INFEASIBLE
test_linear_INFEASIBLE_2
test_linear_Semicontinuous_integration
test_modification_coef_scalar_objective
test_modification_const_scalar_objective
test_modification_delete_variables_in_a_batch
test_modification_set_singlevariable_lessthan
test_modification_transform_singlevariable_lessthan
test_objective_FEASIBILITY_SENSE_clears_objective
test_objective_ObjectiveFunction_constant
test_objective_ObjectiveFunction_duplicate_terms
test_objective_qp_ObjectiveFunction_edge_cases
test_objective_qp_ObjectiveFunction_zero_ofdiag
test_solve_ObjectiveBound_MAX_SENSE_LP
test_solve_ObjectiveBound_MIN_SENSE_LP
test_solve_TerminationStatus_DUAL_INFEASIBLE
test_unbounded_MAX_SENSE
test_unbounded_MAX_SENSE_offset
test_unbounded_MIN_SENSE
test_unbounded_MIN_SENSE_offset
test_variable_solve_with_lowerbound
test_variable_solve_with_upperbound

Suggested fix

In cuOpt.jl's optimize! (MOI_wrapper.jl, around lines 1300-1320), check the termination/solve status before calling cuOptGetPrimalSolution / cuOptGetDualSolution:

  • Skip primal retrieval when the reported status is infeasible/unbounded/presolve-determined.
  • Skip dual retrieval when the model has quadratic/SOC constraints (consistent with the documented C-API behavior).

Impact

Every nightly wheel-tests-cuopt job across all GPU/driver/dependency combinations is marked failed due to this, masking any other genuine regression in that same CI signal. All other nightly test suites (Python LP/MILP/QP/routing/classification) are green.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

awaiting responseThis expects a response from maintainer or contributor depending on who requested in last comment.bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions