{"record":{"id":"89cc603620af4519","repo":"hibernate/hibernate-orm","slug":"invalid-xml-attribute-name-passed-to-xmlattribute","errorCode":null,"errorMessage":"Invalid XML attribute name passed to 'xmlattributes()': %s","messagePattern":"Invalid XML attribute name passed to 'xmlattributes\\(\\)': (.+?)","errorType":"exception","errorClass":"FunctionArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/function/xml/XmlElementFunction.java","lineNumber":70,"sourceCode":"\t\t\t\t\t\t\t\t\tList<? extends SqmTypedNode<?>> arguments,\n\t\t\t\t\t\t\t\t\tString functionName,\n\t\t\t\t\t\t\t\t\tBindingContext bindingContext) {\n\t\t\t\t\t\t\t\t//noinspection unchecked\n\t\t\t\t\t\t\t\tfinal var literal = (SqmLiteral<String>) arguments.get( 0 );\n\t\t\t\t\t\t\t\tfinal String elementName = literal.getLiteralValue();\n\t\t\t\t\t\t\t\tif ( !XmlHelper.isValidXmlName( elementName ) ) {\n\t\t\t\t\t\t\t\t\tthrow new FunctionArgumentException(\n\t\t\t\t\t\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Invalid XML element name passed to 'xmlelement()': %s\",\n\t\t\t\t\t\t\t\t\t\t\t\t\telementName\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( arguments.size() > 1\n\t\t\t\t\t\t\t\t\t\t&& arguments.get( 1 ) instanceof SqmXmlAttributesExpression attributesExpression ) {\n\t\t\t\t\t\t\t\t\tfor ( var entry : attributesExpression.getAttributes().entrySet() ) {\n\t\t\t\t\t\t\t\t\t\tif ( !XmlHelper.isValidXmlName( entry.getKey() ) ) {\n\t\t\t\t\t\t\t\t\t\t\tthrow new FunctionArgumentException(\n\t\t\t\t\t\t\t\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Invalid XML attribute name passed to 'xmlattributes()': %s\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tentry.getKey()\n\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t),\n\t\t\t\tStandardFunctionReturnTypeResolvers.invariant(\n\t\t\t\t\t\ttypeConfiguration.getBasicTypeRegistry().resolve( String.class, SqlTypes.SQLXML )\n\t\t\t\t),\n\t\t\t\tnull\n\t\t);\n\t}\n","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/function/xml/XmlElementFunction.java#L52-L88","documentation":"Thrown when Hibernate validates the arguments of the HQL 'xmlelement()' function and an attribute name supplied through 'xmlattributes()' fails XmlHelper.isValidXmlName(). A valid XML name must be non-empty, start with a letter, '_' or ':', must not start with 'xml' (case-insensitive, reserved per the XML spec), and may only contain letters, digits, '_', ':', '-', or '.'. The check runs while the SQM query is being parsed/validated, before any SQL is executed.","triggerScenarios":"An HQL/criteria query calls xmlelement(name \"person\", xmlattributes(p.name as \"1stName\")) or uses an alias that starts with 'xml' (e.g. as \"xmlId\"), contains a space (as \"first name\"), or contains characters like '@', '#', or '='. Any of these makes isValidXmlName return false for the attribute map key and FunctionArgumentException is thrown at query creation.","commonSituations":"Porting SQL/XML queries from native SQL to HQL where quoted aliases with spaces or numeric prefixes were legal; generating HQL dynamically from user-supplied column labels; XML feeds that want attribute names starting with digits ('2fa', '24h') or with the reserved 'xml' prefix.","solutions":["Change the alias used inside xmlattributes() so it starts with a letter or underscore, e.g. xmlattributes(p.name as \"name\") instead of as \"1stName\"","Remove spaces and special characters from the alias (use '-' or '_' instead of ' ', no '@'/'#')","Rename aliases that start with 'xml'/'XML' (case-insensitive) to something else, e.g. \"dataId\" instead of \"xmlId\"","If a non-legal name is mandatory, build the XML on the Java side instead of via xmlelement()"],"exampleFix":"// before\nselect xmlelement(name \"user\", xmlattributes(p.name as \"1st_name\", p.id as \"xmlId\"))\nfrom Person p\n\n// after\nselect xmlelement(name \"user\", xmlattributes(p.name as \"first_name\", p.id as \"dataId\"))\nfrom Person p","handlingStrategy":"validation","validationCode":"// Mirror of XmlHelper.isValidXmlName - run before assembling HQL\nstatic boolean isValidXmlName(String name) {\n    if (name == null || name.isEmpty()\n            || !(Character.isLetter(name.charAt(0)) || name.charAt(0) == '_' || name.charAt(0) == ':')\n            || name.regionMatches(true, 0, \"xml\", 0, 3)) {\n        return false;\n    }\n    for (int i = 1; i < name.length(); i++) {\n        char c = name.charAt(i);\n        if (!(Character.isLetterOrDigit(c) || c == '_' || c == ':' || c == '-' || c == '.')) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// before building the query:\nif (!isValidXmlName(alias)) throw new IllegalArgumentException(\"alias '\" + alias + \"' is not a valid XML attribute name\");","typeGuard":null,"tryCatchPattern":"try {\n    return session.createQuery(hql, String.class).getSingleResult();\n}\ncatch (FunctionArgumentException e) { // org.hibernate.query.sqm.produce.function\n    throw new IllegalArgumentException(\"xmlattributes() alias is not a valid XML name: \" + e.getMessage(), e);\n}","preventionTips":["Alias every xmlattributes() argument and keep aliases to [A-Za-z_][A-Za-z0-9_:. -]*","Never start an alias with 'xml' (case-insensitive, reserved)","For dynamic query builders, validate aliases with the XmlHelper name rules before concatenating HQL","Keep a test that executes every generated HQL report query so invalid names fail in CI, not production"],"tags":["hibernate","hql","xml","query-validation","xmlelement"],"backgroundTag":"invalid-xml-name","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}