{"record":{"id":"e805831583706561","repo":"apache/druid","slug":"needs-a-number-as-its-first-argument-but-got-s-in","errorCode":null,"errorMessage":"needs a number as its first argument but got %s instead","messagePattern":"needs a number as its first argument but got (.+?) instead","errorType":"validation","errorClass":"ExpressionValidationException","httpStatus":400,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/math/expr/Function.java","lineNumber":4677,"sourceCode":"\n  abstract class SizeFormatFunc implements Function\n  {\n    protected abstract HumanReadableBytes.UnitSystem getUnitSystem();\n\n    @Override\n    public ExprEval apply(List<Expr> args, Expr.ObjectBinding bindings)\n    {\n      final ExprEval valueParam = args.get(0).eval(bindings);\n      if (valueParam.isNumericNull()) {\n        return ExprEval.ofString(null);\n      }\n\n      /**\n       * only LONG and DOUBLE are allowed\n       * For a DOUBLE, it will be cast to LONG before format\n       */\n      if (valueParam.value() != null && !valueParam.type().anyOf(ExprType.LONG, ExprType.DOUBLE)) {\n        throw validationFailed(\n            \"needs a number as its first argument but got %s instead\",\n            valueParam.type()\n        );\n      }\n\n      /**\n       * By default, precision is 2\n       */\n      long precision = 2;\n      if (args.size() > 1) {\n        ExprEval precisionParam = args.get(1).eval(bindings);\n        if (precisionParam.value() == null) {\n          throw validationFailed(\"needs a LONG as its second argument but got null\");\n        }\n        if (!precisionParam.type().is(ExprType.LONG)) {\n          throw validationFailed(\"needs a LONG as its second argument but got %s instead\", precisionParam.type());\n        }\n        precision = precisionParam.asLong();","sourceCodeStart":4659,"sourceCodeEnd":4695,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/math/expr/Function.java#L4659-L4695","documentation":"Thrown by Druid's HUMAN_READABLE_BYTES_FORMAT expression function when the first argument (the byte count to format) is neither LONG nor DOUBLE at validation time. Only numeric values are accepted; a DOUBLE is cast to LONG before formatting.","triggerScenarios":"Calling human_readable_bytes_format with a STRING, BOOLEAN, or other non-numeric first argument, e.g. human_readable_bytes_format('1024') where the string was never cast.","commonSituations":"Ingested size fields stored as strings (CSV/JSON inputs); users forgetting CAST(col AS BIGINT); binding parameters typed as strings from client frameworks.","solutions":["Cast the first argument: CAST(size_bytes AS BIGINT) before calling the function.","Use a numeric literal instead of a quoted one, e.g. human_readable_bytes_format(1024).","Fix ingestion/rollup typing so the column is stored as LONG.","Validate the expression type in a dry-run/EXPLAIN PLAN before running the query."],"exampleFix":"// before\nhuman_readable_bytes_format(byte_str)\n// after\nhuman_readable_bytes_format(CAST(byte_str AS BIGINT))","handlingStrategy":"validation","validationCode":"CAST(size_expr AS BIGINT) -- apply before human_readable_bytes_format","typeGuard":"// only allow numeric args\nif (!(v instanceof Number)) throw new IllegalArgumentException(\"byte count must be numeric\");","tryCatchPattern":null,"preventionTips":["Cast string-typed size columns at ingestion time","Use numeric literals, not quoted numbers","Verify types with EXPLAIN PLAN"],"tags":["druid","expressions","type-mismatch","validation"],"backgroundTag":"type-mismatch","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"}