{"record":{"id":"ef115c1077a509ff","repo":"apache/druid","slug":"first-argument-must-be-constant-string-expression","errorCode":null,"errorMessage":"first argument must be constant STRING expression containing a valid complex type name but got '%s' instead","messagePattern":"first argument must be constant STRING expression containing a valid complex type name but got '(.+?)' instead","errorType":"validation","errorClass":"ExpressionValidationException","httpStatus":400,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/math/expr/BuiltInExprMacros.java","lineNumber":67,"sourceCode":"    @Override\n    public Expr apply(List<Expr> args)\n    {\n      return new ComplexDecodeBase64Expression(args);\n    }\n\n    final class ComplexDecodeBase64Expression extends ExprMacroTable.BaseScalarMacroFunctionExpr\n    {\n      private final ExpressionType complexType;\n      private final TypeStrategy<?> typeStrategy;\n\n      public ComplexDecodeBase64Expression(List<Expr> args)\n      {\n        super(ComplexDecodeBase64ExprMacro.this, args);\n        validationHelperCheckArgumentCount(args, 2);\n        final Expr arg0 = args.get(0);\n\n        if (!arg0.isLiteral()) {\n          throw validationFailed(\n              \"first argument must be constant STRING expression containing a valid complex type name but got '%s' instead\",\n              arg0.stringify()\n          );\n        }\n        if (arg0.isNullLiteral()) {\n          throw validationFailed(\"first argument must be constant STRING expression containing a valid complex type name but got NULL instead\");\n        }\n        final Object literal = arg0.getLiteralValue();\n        if (!(literal instanceof String)) {\n          throw validationFailed(\n              \"first argument must be constant STRING expression containing a valid complex type name but got '%s' instead\",\n              arg0.getLiteralValue()\n          );\n        }\n\n        this.complexType = ExpressionTypeFactory.getInstance().ofComplex((String) literal);\n        try {\n          this.typeStrategy = complexType.getStrategy();","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/math/expr/BuiltInExprMacros.java#L49-L85","documentation":"The complex_decode_base64 expression macro (BuiltInExprMacros.java) requires its first argument to be a constant STRING literal naming a complex type (e.g. 'complexTypeSerializers' payloads like 'druid.metrics.snapshot'). This validationFailed is thrown when the first argument is not a literal expression at all — e.g. a column reference, arithmetic, or another function call.","triggerScenarios":"Calling complex_decode_base64(expr, col) where the first argument is a non-literal expression such as a column reference, CONCAT('x','y'), or any computed expression instead of a quoted string literal.","commonSituations":"Writing SQL like complex_decode_base64(type_column, data_column) instead of hardcoding the type name; templated SQL where the type name is injected as a dynamic expression.","solutions":["Replace the first argument with a constant string literal, e.g. complex_decode_base64('druid.metrics.snapshot', data_col).","If the type name is dynamic, resolve it in the application layer before building the query.","Check stringify() output in the error message to see what expression was actually passed.","Use EXPLAIN to confirm the expression planner sees a literal."],"exampleFix":"// before\nSELECT complex_decode_base64(type_col, base64_col) FROM t\n// after\nSELECT complex_decode_base64('druid.metrics.snapshot', base64_col) FROM t","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":["druid","expressions","sql","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-14T05:17:10.506Z"}