{"record":{"id":"67ab072d051f547f","repo":"hibernate/hibernate-orm","slug":"bindabletype-does-not-implement-bindabletypeimplem","errorCode":null,"errorMessage":"BindableType does not implement BindableTypeImplementor","messagePattern":"BindableType does not implement BindableTypeImplementor","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/BindingContext.java","lineNumber":56,"sourceCode":"\t/**\n\t * Resolve this parameter type to the corresponding {@link SqmBindableType}.\n\t *\n\t * @param <J> the type of the parameter\n\t * @param bindableType the {@link BindableType} representing the type of the parameter,\n\t *                     which may be null if the type is not known\n\t * @return the corresponding {@link SqmBindableType}, or null if the argument was null\n\t *\n\t * @since 7.0\n\t */\n\tdefault <J> @Nullable SqmBindableType<J> resolveExpressible(@Nullable Type<J> bindableType) {\n\t\tif ( bindableType == null ) {\n\t\t\treturn null;\n\t\t}\n\t\telse if ( bindableType instanceof BindableType<J> implementor) {\n\t\t\treturn implementor.resolveExpressible( this );\n\t\t}\n\t\telse {\n\t\t\tthrow new IllegalArgumentException( \"BindableType does not implement BindableTypeImplementor\" );\n\t\t}\n\t}\n}\n","sourceCodeStart":38,"sourceCodeEnd":60,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/BindingContext.java#L38-L60","documentation":"BindingContext.resolveExpressible(Type) (BindingContext.java:48-57) accepts a jakarta.persistence.metamodel.Type and must map it to Hibernate's internal SqmBindableType. It does so by checking whether the object is an org.hibernate.query.BindableType (the internal contract that carries resolveExpressible(BindingContext)); any other implementation of the JPA metamodel Type interface - from another provider, a hand-rolled wrapper, or a mock - is rejected with IllegalArgumentException 'BindableType does not implement BindableTypeImplementor'.","triggerScenarios":"Passing a non-Hibernate implementation of jakarta.persistence.metamodel.Type (custom metamodel wrapper, mock from tests, another JPA provider's metamodel class) into BindingContext.resolveExpressible; writing a custom HQL/SQM function whose ArgumentsValidator or a TypecheckUtil path resolves caller-supplied JPA Type objects; implementing org.hibernate.query.BindableType yourself without following the internal resolution contract.","commonSituations":"Teams building SQM function libraries or criteria extensions on Hibernate's incubating 7.0 SPIs; tests stubbing the JPA metamodel with Mockito and feeding the stub into query validation; wrapping the metamodel for multi-tenancy or auditing and leaking the wrapper into Hibernate query APIs.","solutions":["Pass types obtained from Hibernate's own metamodel only, e.g. sessionFactory.getMetamodel().entity(...) / .embeddable(...), which are JpaMetamodel implementations of BindableType.","If you wrap the metamodel, unwrap to the delegate before handing Types to BindingContext.resolveExpressible.","For custom BindableType implementations, extend Hibernate's SQM type infrastructure rather than implementing the interface from scratch so resolveExpressible(BindingContext) is honored.","In tests, build a real SessionFactory with test mappings instead of mocking the metamodel Type hierarchy."],"exampleFix":"// before\nType<?> t = myWrapperMetamodel.entity(User.class); // custom wrapper Type\nSqmBindableType<?> sqm = bindingContext.resolveExpressible(t); // throws\n\n// after\nType<?> t = ((MetamodelImplementor) sessionFactory.getMetamodel())\n        .entity(User.class); // Hibernate JpaEntityType implements BindableType\nSqmBindableType<?> sqm = bindingContext.resolveExpressible(t);","handlingStrategy":"type-guard","validationCode":"if (bindableType != null && !(bindableType instanceof org.hibernate.query.BindableType<?>)) {\n    throw new IllegalArgumentException(\n        \"Expected a Hibernate BindableType implementation, got \"\n        + bindableType.getClass().getName());\n}","typeGuard":"static boolean isHibernateBindable(jakarta.persistence.metamodel.Type<?> t) {\n    return t instanceof org.hibernate.query.BindableType<?>;\n}","tryCatchPattern":"try {\n    return bindingContext.resolveExpressible(type);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"BindableTypeImplementor\")) {\n        // unwrap custom metamodel wrappers to the Hibernate delegate and retry\n        return bindingContext.resolveExpressible(unwrapToHibernate(type));\n    }\n    throw e;\n}","preventionTips":["Always source metamodel Type objects from Hibernate's own Metamodel (sessionFactory.getMetamodel()).","If you wrap the metamodel, expose the underlying delegate to Hibernate-facing code; never feed wrappers into SQM APIs.","Avoid mocking the JPA metamodel in tests of Hibernate SPI extensions; use a small real SessionFactory."],"tags":["hibernate","sqm","metamodel","criteria","incubating-api","api-misuse"],"backgroundTag":"incompatible-type-implementation","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}