{"record":{"id":"6e62a1c47871c2f6","repo":"hibernate/hibernate-orm","slug":"removetablegroupjoin-not-supported-by-s","errorCode":null,"errorMessage":"removeTableGroupJoin not supported by %s","messagePattern":"removeTableGroupJoin not supported by (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/TableGroup.java","lineNumber":58,"sourceCode":"\n\tList<TableGroupJoin> getTableGroupJoins();\n\n\tList<TableGroupJoin> getNestedTableGroupJoins();\n\n\tboolean canUseInnerJoins();\n\n\tdefault boolean isLateral() {\n\t\treturn false;\n\t}\n\n\tvoid addTableGroupJoin(TableGroupJoin join);\n\n\t/**\n\t * Removes the given table group join from this group's joins. No-op if not\n\t * present. Default implementation is unsupported; concrete groups override.\n\t */\n\tdefault void removeTableGroupJoin(TableGroupJoin join) {\n\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\"removeTableGroupJoin not supported by \" + getClass().getName() );\n\t}\n\n\t/**\n\t * Adds the given table group join before a join as found via the given navigable path.\n\t */\n\tvoid prependTableGroupJoin(NavigablePath navigablePath, TableGroupJoin join);\n\n\t/**\n\t * A nested table group join is a join against a table group,\n\t * that is ensured to be joined against the primary table reference and table reference joins in isolation,\n\t * prior to doing other table group joins e.g.\n\t *\n\t * <code>\n\t * select *\n\t * from entity1 e\n\t * left join (\n\t * \t collection_table c1","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/TableGroup.java#L40-L76","documentation":"removeTableGroupJoin(TableGroupJoin) is a default method on the TableGroup interface that throws UnsupportedOperationException naming the concrete class. Only groups that extend AbstractTableGroup (or delegate through DelegatingTableGroup) actually implement removal. Calling it on any other TableGroup implementation - a QueryPartTableGroup, a custom hand-rolled group - fails.","triggerScenarios":"SQM-to-SQL AST translation paths that rewrite or remove joins (not-found/optional association handling, criteria query rewrites, join de-duplication) invoke removeTableGroupJoin on the target group; the throw happens when that group's class never overrode the method. Custom TableGroup implementations returned from custom TableGroupProducers hit the same wall.","commonSituations":"Upgrading Hibernate to a version that introduced this interface method while a custom TableGroup subclass was not updated; join removal being triggered on non-standard table groups (CTE/query-part/union groups) by @NotFound or fetch rewriting; custom query translators or test harnesses manipulating table groups.","solutions":["Extend AbstractTableGroup (or wrap with DelegatingTableGroup) so removeTableGroupJoin works out of the box","Override removeTableGroupJoin in the custom TableGroup class named in the exception message","Restructure the query/mapping so join removal is not needed (e.g. re-check @NotFound associations that trigger rewriting)","Update custom dialect/extension code to the Hibernate version that added the method"],"exampleFix":"// before\nclass MyTableGroup implements TableGroup { /* no removeTableGroupJoin */ }\n\n// after\nclass MyTableGroup extends AbstractTableGroup {\n    @Override\n    public void removeTableGroupJoin(TableGroupJoin join) {\n        tableGroupJoins.remove( join );\n    }\n}","handlingStrategy":"validation","validationCode":"boolean supportsJoinRemoval(TableGroup group) {\n    return group instanceof AbstractTableGroup || group instanceof DelegatingTableGroup;\n}","typeGuard":null,"tryCatchPattern":"try {\n    group.removeTableGroupJoin( join );\n} catch ( UnsupportedOperationException e ) {\n    if ( e.getMessage() != null && e.getMessage().startsWith( \"removeTableGroupJoin not supported\" ) ) {\n        // rebuild the table group instead of mutating it\n    } else { throw e; }\n}","preventionTips":["Base custom TableGroup implementations on AbstractTableGroup or DelegatingTableGroup","Check the concrete TableGroup type before mutating joins in translation code","Re-check custom table-group code when upgrading Hibernate - interface default methods evolve"],"tags":["hibernate","orm","sql-ast","table-group","unsupported-operation","internal-api"],"backgroundTag":"unsupported-operation-default-impl","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}