apache/druid · error · ParseException

Unable to parse row [%s]

Error message

Unable to parse row [%s]

What it means

JavaScriptParser wraps any exception raised while executing the user-supplied JavaScript function into a ParseException with message "Unable to parse row [%s]". The parser compiles a JS script and calls it to turn each input row into a {key: value} Map; if the script throws, returns a non-Map, or compilation fails, this error is thrown for the offending row.

Source

Thrown at processing/src/main/java/org/apache/druid/java/util/common/parsers/JavaScriptParser.java:83

      final String function
  )
  {
    this.fn = compile(function);
  }

  @Override
  public Map<String, Object> parseToMap(String input)
  {
    try {
      final Object compiled = fn.apply(input);
      if (!(compiled instanceof Map)) {
        throw new ParseException(input, "JavaScript parsed value [%s] must be in {key: value} format!", input);
      }

      return (Map) compiled;
    }
    catch (Exception e) {
      throw new ParseException(input, e, "Unable to parse row [%s]", input);
    }
  }

  @Override
  public void setFieldNames(Iterable<String> fieldNames)
  {
    throw new UnsupportedOperationException();
  }

  @Override
  public List<String> getFieldNames()
  {
    throw new UnsupportedOperationException();
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Inspect the wrapped cause in the ParseException stack trace to find the actual JS error
  2. Verify the JavaScript function returns a plain object ({key: value}), not a string, array, or null
  3. Check that JavaScript is enabled (druid.javascript.enabled=true) in the runtime properties of the involved service
  4. Test the function logic on a sample row locally before deploying the ingestion spec

Example fix

// before
"parseSpec": {"type":"javascript", "function":"function(str) { return JSON.stringify(JSON.parse(str)); }"}
// after
"parseSpec": {"type":"javascript", "function":"function(str) { return JSON.parse(str); }"}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate before ingesting
if (!script.trim().startsWith("function")) throw new IllegalArgumentException("JS must be a function returning {key: value}");
// smoke-test: JSON.parse(functionResult) must yield a plain object

Type guard

function returnsMap(Object v) { return v instanceof java.util.Map; }

Try / catch

try { map = parser.parseToMap(row); } catch (ParseException e) { log.error("Row rejected: {} cause: {}", row, e.getCause()); throw e; }

Prevention

When it happens

Trigger: Calling parseToMap(String) on a row where the configured JavaScript function throws an exception, returns null/non-Map value, or the script itself failed to compile (which surfaces as a ParseException for the first row processed).

Common situations: Ingestion specs using type:'javascript' parseSpec with a buggy or truncated function; script returns a JSON string or array instead of an object; JavaScript engine disabled in runtime.properties (druid.javascript.enabled=false) causing script initialization failure; JS syntax errors after copy-paste.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/ea88fb7a2265647b. Report an issue: GitHub.