{"record":{"id":"1f217482db37e311","repo":"apache/druid","slug":"first-argument-must-be-constant-string-expression-1f2174","errorCode":null,"errorMessage":"first argument must be constant STRING expression containing a valid complex type name but got NULL instead","messagePattern":"first argument must be constant STRING expression containing a valid complex type name but got NULL instead","errorType":"validation","errorClass":"ExpressionValidationException","httpStatus":400,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/math/expr/BuiltInExprMacros.java","lineNumber":73,"sourceCode":"    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();\n        }\n        catch (IllegalArgumentException illegal) {\n          throw validationFailed(\n              \"first argument must be a valid COMPLEX type name, got unknown COMPLEX type [%s]\",\n              complexType.asTypeString()\n          );","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/math/expr/BuiltInExprMacros.java#L55-L91","documentation":"Same complex_decode_base64 first-argument validation in BuiltInExprMacros.java, but this variant fires when the first argument is a literal that is explicitly NULL. A NULL literal cannot name a complex type, so validation fails before any decoding happens.","triggerScenarios":"Calling complex_decode_base64(NULL, data_col) — first argument is a literal NULL string.","commonSituations":"Templated/parameterized SQL where the type-name bind variable was never bound or was bound to NULL; generated SQL from an app where an optional type parameter was omitted.","solutions":["Pass a non-null constant complex type name string as the first argument.","Check application code for unbound/optional parameters that default to NULL.","Verify the parameter substitution in any SQL templating layer.","If type varies per row, decode outside SQL or use a per-type query."],"exampleFix":"// before\ncomplex_decode_base64(NULL, base64_col)\n// after\ncomplex_decode_base64('druid.metrics.snapshot', base64_col)","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":["druid","expressions","sql","null"],"backgroundTag":"null-argument","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}