{"record":{"id":"0ecd66a1306bc76c","repo":"hibernate/hibernate-orm","slug":"index-access-is-only-supported-for-basic-plural-ty","errorCode":null,"errorMessage":"Index access is only supported for basic plural types.","messagePattern":"Index access is only supported for basic plural types\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmFunctionPath.java","lineNumber":133,"sourceCode":"\t\tcreationState.getProcessingStateStack().getCurrent().getPathRegistry().register( sqmPath );\n\t\treturn sqmPath;\n\t}\n\n\t@Override\n\tpublic SqmPath<?> resolveIndexedAccess(\n\t\t\tSqmExpression<?> selector,\n\t\t\tboolean isTerminal,\n\t\t\tSqmCreationState creationState) {\n\t\tfinal var pathRegistry = creationState.getCurrentProcessingState().getPathRegistry();\n\t\tfinal var navigablePath =\n\t\t\t\tgetNavigablePath().append( CollectionPart.Nature.ELEMENT.getName(),\n\t\t\t\t\t\tselector.toHqlString() );\n\t\tfinal var indexedPath = pathRegistry.findFromByPath( navigablePath );\n\t\tif ( indexedPath != null ) {\n\t\t\treturn indexedPath;\n\t\t}\n\t\tif ( !( getReferencedPathSource().getPathType() instanceof BasicPluralType<?, ?> ) ) {\n\t\t\tthrow new UnsupportedOperationException( \"Index access is only supported for basic plural types.\" );\n\t\t}\n\t\tfinal var queryEngine = creationState.getCreationContext().getQueryEngine();\n\t\tfinal SelfRenderingSqmFunction<?> result = queryEngine.getSqmFunctionRegistry()\n\t\t\t\t.getFunctionDescriptor( \"array_get\" )\n\t\t\t\t.generateSqmExpression(\n\t\t\t\t\t\tasList( function, selector ),\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\tqueryEngine\n\t\t\t\t);\n\t\tfinal SqmFunctionPath<?> path = new SqmFunctionPath<>( result );\n\t\tpathRegistry.register( path );\n\t\treturn path;\n\t}\n\n\t@Override\n\tpublic <X> X accept(SemanticQueryWalker<X> walker) {\n\t\treturn walker.visitFunctionPath( this );\n\t}","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmFunctionPath.java#L115-L151","documentation":"SqmFunctionPath.resolveIndexedAccess translates 'f(x)[i]' into an array_get call, but only when the function path's type is a BasicPluralType (an array of basic elements). For any other return type the operation throws UnsupportedOperationException because indexed access on non-basic-array function results has no SQL translation.","triggerScenarios":"HQL 'f(e.x)[1]' or criteria indexed access where the function returns a scalar, an embeddable, an entity, or a non-basic array type; e.g. indexing a function that returns a comma string instead of a typed array.","commonSituations":"Assuming [i] works on any function result after seeing Hibernate 6.6+/7 array indexing; functions returning custom array types without a registered array JdbcType; porting PostgreSQL-style subscripting into HQL.","solutions":["Ensure the function is registered with a basic array return type (e.g. String[]/int[] resolved through the basic type registry) so the path type is a BasicPluralType","Use the explicit array_get(f(x), i) form once the return type is a proper basic array","Wrap the function result in cast(f(x) as String[]) to force a basic-array type before indexing","If you need elements of a structured collection, explode the value first (e.g. string_to_array/split into a typed array)"],"exampleFix":"// before: parse_names returns a plain String\nselect parse_names(p.csv)[1] from Person p\n//  -> UnsupportedOperationException: Index access is only supported for basic plural types.\n\n// after: register the function with String[] return type, then index it\nregistry.register(\"parse_names\", new NamedSqmFunctionDescriptor(\n    \"parse_names\", false, argTypes,\n    StandardFunctionReturnTypeResolvers.instantiate(typeFactory.basicType(String[].class))));\nselect parse_names(p.csv)[1] from Person p","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean indexableFunctionResult(SqmFunctionPath<?> path) {\n    return path.getReferencedPathSource().getPathType() instanceof BasicPluralType<?, ?>;\n}","tryCatchPattern":"try {\n    element = functionPath.resolveIndexedAccess(selector, true, creationState);\n} catch (UnsupportedOperationException e) {\n    // not a basic array: register the function with String[]/int[] return type, or use array_get on a typed array\n    throw new IllegalStateException(\"Indexed access requires a basic-array-typed function\", e);\n}","preventionTips":["Register array-returning functions with explicit basic array types (String[], int[])","Check the function path type is BasicPluralType before using [i] syntax","Use array_get(f(x), i) explicitly and ensure the argument is a typed array","Cast function results to a basic array type before indexing when in doubt"],"tags":["hibernate","hql","array-indexing","custom-function","sqm"],"backgroundTag":"hql-array-indexing","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}