apache/druid · error · JsonMappingException

Invalid JSON inside unknown key:

Error message

Invalid JSON inside unknown key: 

What it means

ResponseContextDeserializer.skipValue throws JsonMappingException when it encounters structured JSON (non-scalar, and not START_OBJECT/START_ARRAY per its switch) inside a value for an unknown response-context key while deserializing the response context header. It means the header contained JSON it could not safely skip or interpret.

Source

Thrown at processing/src/main/java/org/apache/druid/query/context/ResponseContextDeserializer.java:98

  /**
   * Skip over a single JSON value: scalar or composite.
   */
  private void skipValue(final JsonParser jp, String key) throws IOException
  {
    final JsonToken token = jp.currentToken();
    switch (token) {
      case START_OBJECT:
        skipTo(jp, JsonToken.END_OBJECT);
        break;
      case START_ARRAY:
        skipTo(jp, JsonToken.END_ARRAY);
        break;
      default:
        if (token.isScalarValue()) {
          return;
        }
        throw new JsonMappingException(jp, "Invalid JSON inside unknown key: " + key);
    }
  }

  /**
   * Freewheel over the contents of a structured object, including any
   * nested structured objects, until the given end token.
   */
  private void skipTo(final JsonParser jp, JsonToken end) throws IOException
  {
    while (true) {
      jp.nextToken();
      final JsonToken token = jp.currentToken();
      if (token == null) {
        throw new JsonMappingException(jp, "Premature EOF");
      }
      switch (token) {
        case START_OBJECT:
          skipTo(jp, JsonToken.END_OBJECT);

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Align Druid versions across the cluster so all nodes understand the same response-context keys
  2. Inspect the raw header value to find the offending unknown key and its malformed JSON
  3. Remove or fix the unknown key from the serialized context
  4. If writing custom deserialization, extend skipValue to handle the new token type

Example fix

// before
throw new JsonMappingException(jp, "Invalid JSON inside unknown key: " + key);
// after
if (token.isStructStart()) { skipTo(jp, token == JsonToken.START_OBJECT ? JsonToken.END_OBJECT : JsonToken.END_ARRAY); return; }
throw new JsonMappingException(jp, "Invalid JSON inside unknown key: " + key);
Defensive patterns

Strategy: try-catch

Validate before calling

// validate header JSON shape before deserializing
JsonNode n = mapper.readTree(headerValue);
if (!n.isObject()) { throw new IllegalArgumentException("response context must be a JSON object"); }

Try / catch

try { rc = mapper.readValue(headerValue, ResponseContext.class); } catch (JsonMappingException e) { log.warn(e, "invalid response context"); rc = ResponseContext.createEmpty(); }

Prevention

When it happens

Trigger: Deserializing a Base64/JSON-encoded ResponseContext (e.g. the X-Druid-Response-Context header) that contains an unknown key whose value is a structured token the deserializer's skip logic doesn't recognize.

Common situations: Cluster version skew where a newer node emits new response-context key types an older deserializer doesn't know; corrupted or hand-edited response context headers; proxy layers rewriting header values.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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