{"record":{"id":"cff3aa6bb6e91ef5","repo":"hibernate/hibernate-orm","slug":"cockroachdb-json-value-only-support-literal-json-p-cff3aa","errorCode":null,"errorMessage":"CockroachDB json_value only support literal json paths, but got \" + arguments.jsonPath()","messagePattern":"CockroachDB json_value only support literal json paths, but got \" \\+ arguments\\.jsonPath\\(\\)","errorType":"exception","errorClass":"QueryException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/function/json/CockroachDBJsonValueFunction.java","lineNumber":50,"sourceCode":"\t@Override\n\tprotected void render(\n\t\t\tSqlAppender sqlAppender,\n\t\t\tJsonValueArguments arguments,\n\t\t\tReturnableType<?> returnType,\n\t\t\tSqlAstTranslator<?> walker) {\n\t\t// jsonb_path_query_first errors by default\n\t\tif ( arguments.errorBehavior() != null && arguments.errorBehavior() != JsonValueErrorBehavior.ERROR ) {\n\t\t\tthrow new QueryException( \"Can't emulate on error clause on CockroachDB\" );\n\t\t}\n\t\tif ( arguments.emptyBehavior() != null && arguments.emptyBehavior() != JsonValueEmptyBehavior.NULL ) {\n\t\t\tthrow new QueryException( \"Can't emulate on empty clause on CockroachDB\" );\n\t\t}\n\t\tfinal String jsonPath;\n\t\ttry {\n\t\t\tjsonPath = walker.getLiteralValue( arguments.jsonPath() );\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new QueryException( \"CockroachDB json_value only support literal json paths, but got \" + arguments.jsonPath() );\n\t\t}\n\t\tappendJsonValue(\n\t\t\t\tsqlAppender,\n\t\t\t\targuments.jsonDocument(),\n\t\t\t\tJsonPathHelper.parseJsonPathElements( jsonPath ),\n\t\t\t\targuments.isJsonType(),\n\t\t\t\targuments.passingClause(),\n\t\t\t\targuments.returningType(),\n\t\t\t\twalker\n\t\t);\n\t}\n\n\tprivate static boolean isBinary(@Nullable CastTarget castTarget) {\n\t\treturn castTarget != null && castTarget.getJdbcMapping().getJdbcType().isBinary();\n\t}\n\n\tstatic void appendJsonValue(SqlAppender sqlAppender, Expression jsonDocument, List<JsonPathHelper.JsonPathElement> jsonPathElements, boolean isJsonType, JsonPathPassingClause jsonPathPassingClause, CastTarget castTarget, SqlAstTranslator<?> walker) {\n\t\tfinal boolean isBinary = isBinary( castTarget );","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/function/json/CockroachDBJsonValueFunction.java#L32-L68","documentation":"The CockroachDB json_value() emulation cannot pass the JSON path through to the database: it parses the path string (JsonPathHelper.parseJsonPathElements) and re-renders it as jsonb path constructor elements with dialect-quoted literals. That rewrite is only possible when the path is a compile-time string literal; walker.getLiteralValue() fails for bind parameters and computed expressions, and Hibernate rethrows as this QueryException during SQL rendering.","triggerScenarios":"json_value() on the CockroachDB dialect whose second argument is not a string literal, e.g. select json_value(d.doc, :path) from Document d, or a path built with string concatenation or a function call. Note that PASSING does not help here - the path argument itself must be a literal.","commonSituations":"Reusable repository methods that store the JSON path in a variable or receive it from the UI; code migrated from the PostgreSQL dialect where a parameterized path worked; report generators that build paths dynamically.","solutions":["Inline the path as a string literal: json_value(d.doc, '$.items[0].name')","Keep the path literal and parameterize only varying parts inside it via PASSING: json_value(d.doc, '$.items[$i]' passing :idx as i)","Maintain a bounded whitelist of literal-path queries instead of one parameterized query","Fall back to a native SQL query using jsonb_path_query_first() for fully dynamic paths"],"exampleFix":"// before - path bound as a query parameter, throws on CockroachDB\nselect json_value(d.doc, :path) from Document d\n\n// after - literal path; parameterize sub-parts with the passing clause\nselect json_value(d.doc, '$.items[$i]' passing :idx as i) from Document d","handlingStrategy":"validation","validationCode":"// Heuristic lint: json_* paths must be string literals, not bind parameters\nprivate static final Pattern PARAM_JSON_PATH =\n    Pattern.compile(\"(?i)json_(value|exists|query|table)\\\\s*\\\\([^,]+,\\\\s*:\\\\w+\");\n\nstatic void assertLiteralJsonPaths(String hql) {\n    if (PARAM_JSON_PATH.matcher(hql).find()) {\n        throw new IllegalArgumentException(\n            \"JSON path must be a string literal on CockroachDB/H2; use PASSING for variable parts\");\n    }\n}","typeGuard":"// Java predicate (type-guard analogue) for Criteria/SQM path expressions\nstatic boolean isLiteralPath(org.hibernate.query.sqm.tree.expression.SqmExpression<?> pathExpr) {\n    return pathExpr instanceof org.hibernate.query.sqm.tree.expression.SqmLiteral<?>;\n}","tryCatchPattern":"try {\n    return session.createQuery(hql, String.class).getResultList();\n} catch (org.hibernate.QueryException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"only support literal json paths\")) {\n        throw new IllegalArgumentException(\n            \"JSON path must be a literal on this dialect; got: \" + hql, e);\n    }\n    throw e;\n}","preventionTips":["Write JSON paths as string literals in HQL; parameterize varying indexes/attributes with the PASSING clause","Never route user-supplied JSON paths into json_* bind parameters on H2/CockroachDB","Add one repository-layer test per dialect that executes every json_* query your code ships"],"tags":["hibernate","cockroachdb","json","hql","json-value","json-path","bind-parameter"],"backgroundTag":"non-literal-json-path","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}