openzipkin/zipkin · error · IllegalArgumentException
Not a valid JSON object, start token: {}
Error message
Not a valid JSON object, start token: {} What it means
parseEndpoint decodes the localEndpoint/remoteEndpoint field of a span and requires it to be a JSON object; a non-object start token throws IllegalArgumentException naming the token. Fields inside (serviceName, ipv4, ipv6, port) are then read; an object with all-null/zero values returns null.
Source
Thrown at zipkin-storage/elasticsearch/src/main/java/zipkin2/elasticsearch/internal/JsonSerializers.java:120
}
break;
case "debug":
result.debug(parser.getBooleanValue());
break;
case "shared":
result.shared(parser.getBooleanValue());
break;
default:
// Skip
}
}
return result.build();
}
static Endpoint parseEndpoint(JsonParser parser) throws IOException {
if (!parser.isExpectedStartObjectToken()) {
throw new IllegalArgumentException("Not a valid JSON object, start token: " +
parser.currentToken());
}
String serviceName = null, ipv4 = null, ipv6 = null;
int port = 0;
while (parser.nextToken() != JsonToken.END_OBJECT) {
JsonToken value = parser.nextValue();
if (value == JsonToken.VALUE_NULL) {
continue;
}
switch (parser.currentName()) {
case "serviceName":
serviceName = parser.getText();
break;
case "ipv4":
ipv4 = parser.getText();View on GitHub (pinned to 878ce2a1fa)
Solutions
- Fix the document: endpoint must be an object like "localEndpoint":{"serviceName":"frontend","ipv4":"10.0.0.1","port":8080}.
- Fix the converting pipeline to build the object shape.
- Remove/reindex malformed documents.
- In Java, set endpoints via Span.Builder.localEndpoint(Endpoint...) so encoding is handled.
Example fix
// before
{"traceId":"abc","id":"def","localEndpoint":"frontend"}
// -> IllegalArgumentException: Not a valid JSON object, start token: VALUE_STRING
// after
{"traceId":"abc","id":"def","localEndpoint":{"serviceName":"frontend"}} Defensive patterns
Strategy: type-guard
Validate before calling
var span = objectMapper.readTree(spanJson);
for (String f : new String[]{"localEndpoint", "remoteEndpoint"}) {
JsonNode e = span.get(f);
if (e != null && !e.isObject()) throw new IOException(f + " must be an object");
} Type guard
boolean endpointWellFormed(JsonNode span, String field) {
JsonNode e = span.get(field);
return e == null || e.isObject();
} Try / catch
try { Span s = SPAN_PARSER.parse(p); }
catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Not a valid JSON object") && rawJson.contains("Endpoint")) {
// endpoint field is not an object; fix producer to emit {serviceName,...}
}
} Prevention
- Encode endpoints as objects with serviceName/ipv4/ipv6/port keys.
- Set endpoints via Span.Builder.localEndpoint(Endpoint.newBuilder()...) in code.
- When converting from OTel/Jaeger, map resource attributes into an endpoint object.
When it happens
Trigger: A span document where "localEndpoint" or "remoteEndpoint" is a string, array, or number — e.g. "localEndpoint":"frontend" — parsed by SPAN_PARSER.
Common situations: Simplified hand-written fixtures that inline the service name; converters from other formats (OpenTelemetry, Jaeger) emitting endpoint as a scalar; custom writers inserting documents into Zipkin indices.
Related errors
- Invalid span, expecting annotations array start, got: {}
- Invalid span, expecting tags object, got: {}
- Not a valid JSON object, start token: %s
- End of input while parsing object.
- Incomplete annotation at {}
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/6c8dbd89e5dd9580.
Report an issue: GitHub.