json-path/JsonPath · error · JsonPathException

Not a JSON Node

Error message

Not a JSON Node

What it means

Jackson3JsonNodeJsonProvider.toJson serializes a tree node back to a JSON string and requires the argument to be a Jackson JsonNode. Passing any other object type (raw Maps, Lists, provider-internal wrappers) violates the provider's model contract, so JsonPathException('Not a JSON Node') is thrown.

Source

Thrown at json-path/src/main/java/com/jayway/jsonpath/spi/json/Jackson3JsonNodeJsonProvider.java:79

            return objectMapper.readTree(json);
        } catch (JacksonException e) {
            throw new InvalidJsonException(e, new String(json, StandardCharsets.UTF_8));
        }
    }

    @Override
    public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException {
        try {
            return objectMapper.readTree(new InputStreamReader(jsonStream, charset));
        } catch (IOException e) {
            throw new InvalidJsonException(e);
        }
    }

    @Override
    public String toJson(Object obj) {
        if (!(obj instanceof JsonNode)) {
            throw new JsonPathException("Not a JSON Node");
        }
        return obj.toString();
    }

    @Override
    public Object createArray() {
        return JsonNodeFactory.instance.arrayNode();
    }

    @Override
    public Object createMap() {
        return JsonNodeFactory.instance.objectNode();
    }

    public Object unwrap(Object o) {
        if (o == null) {
            return null;
        }

View on GitHub (pinned to 62a4c9f0f6)

Solutions

  1. Only pass JsonNode instances to toJson; re-parse raw objects with this provider first (toJsonNode/mapToNode)
  2. Use the matching provider for the object model you hold (Jackson3JsonProvider.toJson for parsed Object trees)
  3. Convert the value: ObjectMapper.valueToTree(obj) to obtain a JsonNode before calling toJson
  4. Standardize on one JsonProvider for both parse and serialize in your Configuration

Example fix

// before
String s = nodeProvider.toJson(myMap); // JsonPathException
// after
JsonNode node = objectMapper.valueToTree(myMap);
String s = nodeProvider.toJson(node);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(obj instanceof JsonNode)) throw new IllegalArgumentException("toJson requires a JsonNode, got: " + obj.getClass());

Type guard

boolean isJsonNode(Object o) { return o instanceof JsonNode; }

Try / catch

try {
    return provider.toJson(obj);
} catch (JsonPathException e) {
    return objectMapper.valueToTree(obj).toString();
}

Prevention

When it happens

Trigger: Calling toJson(obj) on an object that is not com.fasterxml.jackson.../tools.jackson JsonNode — e.g. a Map returned by another provider, or the unwrapped POJO result of a read; mixing providers (parsing with Jackson3JsonProvider but serializing via the JsonNode provider or vice versa); passing user-created data structures directly to the provider.

Common situations: Code that pipes results from one JsonPath configuration into a provider expecting its own node type; migrations between Jackson databind provider and JsonNode provider where object models differ; generic utility code assuming all providers use Maps.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11). Data as JSON: /api/errors/746a7b8867896c85. Report an issue: GitHub.