Friday, February 18, 2022

Wanted: better error messages

In [1] a user tries the following constraint:
mdl.addConstrs((t[i,k] * X[i,j,k] - te1[i] <= 5) >> (z1[i,k] == 1) for i,j,k in arcos if i != 0 and i != 23)
(t and X and variables). This is not accepted, and the following error message is issued:

AttributeError: 'gurobipy.QuadExpr' object has no attribute 'getVar'

This is a terrible error message. It does not describe the real, underlying problem, and it does not tell the user what to do next. Developers typically do not pay much attention to error messages. Often they seem more aimed to make life easy for the developer than providing assistance to an already confused user. In this case, I believe the modeling tool did not even issue an error message, but rather made assumptions without checking, and left it to the Python run-time system to complain. 

This constraint has two problems: 
  • Indicator constraints have a simple binary variable as condition, not a general (boolean) expression
  • Only linear constraints are supported in indicator constraints

Maybe a better message is:

Indicator constraints have the form:

        binary variable == 0 ==> linear constraint


        binary variable == 1 ==> linear constraint 

Your constraint does not have this form. You need to reformulate it to fit this format, or use a different (big-M) formulation.

Well-formed and meaningful error messages are very important. The user is already confused, otherwise (s)he would formulate a correct constraint. Adding confusing error messages to this confusion is not a good idea. A good error message could have prevented this post. We can think of error messages as the UI (User Interface) when it really matters: when the user needs help. Developers should pay much more attention to this.

A question for another day is of course: why are only linear constraints supported?


  1. AttributeError: 'gurobipy.QuadExpr' object has no attribute 'getVar',


  1. In this case, it is a Python language error. As long as you rely on a general-purpose programming language like Python, you are limited to the errors from its parser.

  2. The statement does not even contain an explicit call to the `getVar` method, so the mistake should have been caught at another level, closer to the user code?

    1. My guess is that the Gurobi code for the operator overloading is making assumptions that are not checked.