diff --git a/src/plugins/variational_constraints/variational_constraints_engine.jl b/src/plugins/variational_constraints/variational_constraints_engine.jl index 3d0326aa..50ea6ffe 100644 --- a/src/plugins/variational_constraints/variational_constraints_engine.jl +++ b/src/plugins/variational_constraints/variational_constraints_engine.jl @@ -646,7 +646,7 @@ function materialize_constraints!(model::Model, node_label::NodeLabel, node_data if !is_valid_partition(constraint_set) error( - lazy"Factorization constraint set at node $node_label is not a valid constraint set. Please check your model definition and constraint specification. (Constraint set: $constraint_bitset)" + lazy"Factorization constraint set at node $node_label is not a valid constraint set. Please check your model definition and constraint specification. (Constraint set: $constraint_bitset)\n\nHint: A valid constraint set requires that each interface belongs to exactly one factorization group. In the constraint matrix, each column must have exactly one non-zero entry per group. Make sure all variables appearing in your model are included in your factorization constraint." ) end diff --git a/test/plugins/variational_constraints/variational_constraints_engine_tests.jl b/test/plugins/variational_constraints/variational_constraints_engine_tests.jl index 3efaf513..937e259a 100644 --- a/test/plugins/variational_constraints/variational_constraints_engine_tests.jl +++ b/test/plugins/variational_constraints/variational_constraints_engine_tests.jl @@ -1596,3 +1596,42 @@ end @test map(rhs, collect(stack)) == [:a] end +@testitem "invalid factorization constraint set throws a descriptive error with a hint" begin + using BitSetTuples + import GraphPPL: + create_model, + with_plugins, + materialize_constraints!, + getcontext, + setextra!, + VariationalConstraintsPlugin, + PluginsCollection, + VariationalConstraintsFactorizationBitSetKey + + include("../../testutils.jl") + + using .TestUtils.ModelZoo + + # A constraint set where the same interface appears in more than one group is invalid: + # `((1,), (3,), (1, 3))` puts interface `1` in both the first and the third group. + model = create_model(with_plugins(simple_model(), PluginsCollection(VariationalConstraintsPlugin()))) + ctx = getcontext(model) + node = ctx[NormalMeanVariance, 2] + + setextra!(model[node], VariationalConstraintsFactorizationBitSetKey, BoundedBitSetTuple(((1,), (3,), (1, 3)))) + + error = try + materialize_constraints!(model, node) + nothing + catch e + e + end + + @test error !== nothing + @test error isa ErrorException + message = sprint(showerror, error) + @test occursin("not a valid constraint set", message) + @test occursin("valid constraint set requires", message) + @test occursin("each interface belongs to exactly one factorization group", message) + @test occursin("Hint", message) +end \ No newline at end of file