{"record":{"id":"45ba685f87195fd1","repo":"hasura/graphql-engine","slug":"the-boolean-expression-type-boolean-expression-t-45ba68","errorCode":null,"errorMessage":"the boolean expression type '{boolean_expression_type}' used in the comparable relationship '{relationship_name}' does not have an object aggregate operand","messagePattern":"the boolean expression type '(.+?)' used in the comparable relationship '(.+?)' does not have an object aggregate operand","errorType":"validation","errorClass":"AggregateBooleanExpressionError","httpStatus":null,"severity":"error","filePath":"v3/crates/metadata-resolve/src/stages/aggregate_boolean_expressions/types.rs","lineNumber":337,"sourceCode":"    #[error(\n        \"the comparable relationship '{relationship_name}' for the operand type '{operand_type}' targets a model than cannot be found: '{target_model_name}'\"\n    )]\n    ComparableRelationshipTargetModelNotFound {\n        operand_type: Qualified<CustomTypeName>,\n        relationship_name: open_dds::relationships::RelationshipName,\n        target_model_name: Qualified<open_dds::models::ModelName>,\n    },\n\n    #[error(\n        \"the comparable relationship '{relationship_name}' for the operand type '{operand_type}' references a boolean expression type that cannot be found: '{boolean_expression_type}'\"\n    )]\n    ComparableRelationshipBooleanExpressionNotFound {\n        operand_type: Qualified<CustomTypeName>,\n        relationship_name: open_dds::relationships::RelationshipName,\n        boolean_expression_type: Qualified<CustomTypeName>,\n    },\n\n    #[error(\n        \"the boolean expression type '{boolean_expression_type}' used in the comparable relationship '{relationship_name}' does not have an object aggregate operand\"\n    )]\n    ComparableRelationshipBooleanExpressionIncorrectOperandType {\n        relationship_name: open_dds::relationships::RelationshipName,\n        boolean_expression_type: Qualified<CustomTypeName>,\n    },\n\n    #[error(\n        \"the object type of the target of the relationship '{relationship_name}' ({relationship_target_object_type}) does not match the operand type of the boolean expression type '{boolean_expression_type}': '{boolean_expression_operand_type}'\"\n    )]\n    ComparableRelationshipBooleanExpressionTypeMismatch {\n        relationship_name: open_dds::relationships::RelationshipName,\n        relationship_target_object_type: Qualified<CustomTypeName>,\n        boolean_expression_type: Qualified<CustomTypeName>,\n        boolean_expression_operand_type: Qualified<CustomTypeName>,\n    },\n\n    #[error(\"the filter input model '{model_name}' cannot be found\")]","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/metadata-resolve/src/stages/aggregate_boolean_expressions/types.rs#L319-L355","documentation":"While resolving comparable relationships, the metadata resolver found the boolean expression type referenced by the relationship, but that boolean expression type has no operand of an object aggregate type. Comparable relationships rely on the boolean expression type having an object aggregate operand (the target type being aggregated/compared), so the relationship cannot be resolved. This is thrown during metadata-resolve's aggregate_boolean_expressions stage when validating the shape of the named boolean expression type.","triggerScenarios":"Defining an open_dds comparable relationship whose boolean_expression_type points at a boolean expression type whose operands are all scalar comparisons (or the operand is not the object-aggregate-shaped operand), e.g. a relationship on type A targeting type B but reusing a boolean expression type built for scalar/explosion operands instead of the _aggregate operand for B.","commonSituations":"Copying a boolean expression type from another type and pointing a comparable relationship at it; upgrading OpenDD spec versions where operand kinds were split into object aggregate vs comparison operands; hand-writing the boolean expression type instead of deriving it.","solutions":["Check the operand list of the boolean expression type named in the error and add an operand whose type is an object aggregate operand matching the relationship target.","Point the relationship's boolean_expression_type at the correct boolean expression type defined for the relationship's target object type.","If the target type is wrong, fix the relationship target so it matches the object aggregate operand that already exists."],"exampleFix":"# before\nboolean_expressions:\n  ArticleBoolExp:\n    operands:\n      title: StringComparison  # no object aggregate operand\nrelationships:\n  comparable:\n  - name: articleComparable\n    boolean_expression_type: ArticleBoolExp\n    target_object_type: Article\n# after\nboolean_expressions:\n  ArticleBoolExp:\n    operands:\n      title: StringComparison\n      _aggregate: ArticleAggregateBoolExp  # object aggregate operand for target Article","handlingStrategy":"validation","validationCode":"// before resolving, verify the boolean expression type used by each comparable relationship\n// has an object-aggregate operand:\nfn has_object_aggregate_operand(bool_exp: &BooleanExpressionType) -> bool {\n    bool_exp.operands.iter().any(|op| matches!(op.kind, OperandKind::ObjectAggregate { .. }))\n}\n\nfor rel in &metadata.comparable_relationships {\n    let be = bool_exp_types.get(&rel.boolean_expression_type)\n        .expect(\"boolean expression type must exist\");\n    assert!(has_object_aggregate_operand(be),\n        \"{} lacks an object aggregate operand\", rel.boolean_expression_type);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive boolean expression types from the target object type instead of hand-writing them.","Run metadata resolve in CI to catch operand-shape errors before deploy."],"tags":["metadata","boolean-expression","comparable-relationship","open-dds"],"backgroundTag":"metadata-validation-failed","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}