{"record":{"id":"14b94ae1214b5a3f","repo":"hibernate/hibernate-orm","slug":"illegal-interpolation-s-s-is-a-field-alias","errorCode":null,"errorMessage":"Illegal interpolation '%s' ('%s' is a field alias)","messagePattern":"Illegal interpolation '(.+?)' \\('(.+?)' is a field alias\\)","errorType":"exception","errorClass":"QueryException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sql/internal/SQLQueryParser.java","lineNumber":226,"sourceCode":"\t\t\tcase \"h-catalog\":\n\t\t\t\tif ( defaultCatalog != null ) {\n\t\t\t\t\tresult.append( defaultCatalog.render(dialect) );\n\t\t\t\t\tresult.append( \".\" );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new QueryException( \"Unknown placeholder \", token);\n\t\t}\n\t}\n\n\tprivate String resolveCollectionProperties(String aliasName, String propertyName, String token) {\n\t\tfinal var fieldResults = context.getPropertyResultsMap( aliasName );\n\t\tfinal var collectionPersister = context.getCollectionPersister( aliasName );\n\t\tfinal String collectionSuffix = context.getCollectionSuffix( aliasName );\n\t\tswitch ( propertyName ) {\n\t\t\tcase \"*\":\n\t\t\t\tif ( !fieldResults.isEmpty() ) {\n\t\t\t\t\tthrow new QueryException(\n\t\t\t\t\t\t\t\"Illegal interpolation '%s' ('%s' is a field alias)\"\n\t\t\t\t\t\t\t\t\t.formatted( token, aliasName ),\n\t\t\t\t\t\t\toriginalQueryString\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\taliasesFound++;\n\t\t\t\treturn collectionPersister.selectFragment( aliasName, collectionSuffix )\n\t\t\t\t\t\t+ \", \" + resolveProperties( aliasName, propertyName, token );\n\t\t\tcase \"element.*\":\n\t\t\t\treturn resolveProperties( aliasName, \"*\", token );\n\t\t\tdefault:\n\t\t\t\t// Let return-properties override whatever the persister has for aliases.\n\t\t\t\tString[] columnAliases = fieldResults.get( propertyName );\n\t\t\t\tif ( columnAliases == null ) {\n\t\t\t\t\tcolumnAliases =\n\t\t\t\t\t\t\tcollectionPersister.getCollectionPropertyColumnAliases( propertyName, collectionSuffix );\n\t\t\t\t}\n\t\t\t\tvalidate( aliasName, propertyName, columnAliases, token );","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sql/internal/SQLQueryParser.java#L208-L244","documentation":"For a collection alias in a legacy native query, interpolating '{alias.*}' asks Hibernate to render the persister's full select fragment. SQLQueryParser.resolveCollectionProperties refuses when the alias has explicit field results (a property->column-alias map from <return-property>/addProperty/@FieldResult), because '*' would conflict with the hand-declared column aliases — it throws QueryException labeling the interpolation illegal.","triggerScenarios":"A native query mixing 'select {items.*} ...' with a mapping that declares property results for alias 'items' — e.g. hbm.xml <load-collection alias=\"items\"> with nested <return-property> entries, or programmatic .addProperty(\"amount\", \"itm_amount\") on a collection return.","commonSituations":"Legacy hbm.xml resultset mappings where column aliases were customized per property; partial modernization that keeps {alias.*} in the SQL while adding explicit field mappings; copying entity-style mappings onto collection joins.","solutions":["Drop the explicit property/field results for that alias so '*' is legal again.","Or stop using '{alias.*}' and reference the mapped properties explicitly in the SQL ({alias.prop} for each).","Modernize the mapping away from hbm.xml interpolation to @SqlResultSetMapping or entity association fetching."],"exampleFix":"-- before (mapping declares return-property entries for alias 'items')\nselect {i.*}, {items.*} from item i, order_items items ...\n\n-- after: interpolate only when no explicit field aliases exist, or list them\nselect {i.*}, {items.itemId} {items.amount} from item i, order_items items ...","handlingStrategy":"validation","validationCode":"// before finalizing a legacy native query: if the alias has explicit property results, forbid {alias.*}\nboolean hasFieldResults = mappingContext.hasPropertyResults(\"items\"); // mirrors getPropertyResultsMap(aliasName).isEmpty()\nif (hasFieldResults && sql.contains(\"{items.*}\")) throw new IllegalStateException(\"Alias 'items' declares field results — {items.*} interpolation is illegal\");","typeGuard":null,"tryCatchPattern":"try { query.list(); } catch (org.hibernate.QueryException e) { /* on 'Illegal interpolation', remove {alias.*} or drop the explicit property aliases */ throw e; }","preventionTips":["Keep a single source of truth per alias: either full '*' interpolation or explicit property aliases, never both.","When adding <return-property>/addProperty to a mapping, search the SQL for {alias.*} and update it in the same commit."],"tags":["hibernate","native-query","interpolation","collection-mapping","legacy-mapping"],"backgroundTag":"native-query-interpolation-conflict","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}