Optimal with IPOPTH, Infeasible with Gurobi

Also, it is odd to me that Gurobi returns infeasibility rather than taking a longer time, as this means Gurobi fails to find any feasible point if I understand it correctly.

I suggest you read https://www.gurobi.com/documentation/9.0/refman/num_grb_guidelines_for_num.html

Is there a smart way to check the feasibility?

Not really. You can use something like the following:

model = Model()
@variable(model, x >= 0)
@variable(model, y >= 0)
c = @constraint(model, x * y <= 1)
o = constraint_object(c)
value(o.func)  # left-hand side
o.set.upper  # right-hand side, if <=. Use .lower if >=, and .value if ==
1 Like