{"record":{"id":"5201fb56bb698b33","repo":"apache/druid","slug":"s-argument-must-be-a-literal","errorCode":null,"errorMessage":"%s argument must be a literal","messagePattern":"(.+?) argument must be a literal","errorType":"validation","errorClass":"DruidException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/math/expr/NamedFunction.java","lineNumber":125,"sourceCode":"        satisfied = true;\n        break;\n      }\n    }\n    if (!satisfied) {\n      throw validationFailed(\n          \"requires %s arguments\",\n          Strings.join(\" or \", () -> Arrays.stream(counts).mapToObj(String::valueOf).iterator())\n      );\n    }\n  }\n\n  /**\n   * Helper method for implementors performing validation to check that an argument is a literal\n   */\n  default void validationHelperCheckArgIsLiteral(Expr arg, String argName)\n  {\n    if (!arg.isLiteral()) {\n      throw validationFailed(\n          \"%s argument must be a literal\",\n          argName\n      );\n    }\n  }\n\n  /**\n   * Helper method for implementors performing validation to check that the argument list is some expected size.\n   *\n   * The parser decomposes a function like 'fold((x, acc) -> x + acc, col, 0)' into the {@link LambdaExpr}\n   * '(x, acc) -> x + acc' and the list of arguments, ['col', 0], and so does not include the {@link LambdaExpr} here.\n   * To compensate for this, the error message will indicate that at least count + 1 arguments are required to count\n   * the lambda.\n   */\n  default void validationHelperCheckArgumentCount(LambdaExpr lambdaExpr, List<Expr> args, int count)\n  {\n    if (args.size() != count) {\n      throw validationFailed(\"requires %s arguments\", count + 1);","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/math/expr/NamedFunction.java#L107-L143","documentation":"A NamedFunction requires a specific argument to be a compile-time literal (e.g. a format string or timezone), but a non-literal expression was supplied. validationHelperCheckArgIsLiteral checks Expr.isLiteral() and throws naming the argument.","triggerScenarios":"Passing a column reference or computed expression where the function demands a literal, e.g. TIME_FORMAT(col, someColumn) or LIKE-style functions requiring a literal pattern argument.","commonSituations":"Users expecting function parameters to accept dynamic values; query builders binding runtime values into positions reserved for literals.","solutions":["Inline the value as a quoted literal string/number","Pre-compute the value outside the expression","If dynamism is required, choose a different function that accepts non-literal arguments"],"exampleFix":"// before\ntime_format(ts, tz_col)\n// after\ntime_format(ts, 'America/Los_Angeles')","handlingStrategy":"validation","validationCode":"if (!(argExpr instanceof LiteralExpr || argExpr.isLiteral())) { throw new IllegalArgumentException(argName + \" must be a compile-time literal\"); }","typeGuard":"boolean isLiteralArg(Expr e) { return e != null && e.isLiteral(); }","tryCatchPattern":"try { expr = Parser.parse(exprString); } catch (ExpressionValidationException e) { // prompt user to inline the literal value }","preventionTips":["Inline literal parameters (formats, timezones, patterns) directly","Compute dynamic values outside the expression","Check function docs for literal-only parameters"],"tags":["expression","literal-required","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}