{"record":{"id":"a8fa3dec6ed5977e","repo":"openzipkin/zipkin","slug":"expected-start-of-dependency-link-object-but-was","errorCode":null,"errorMessage":"Expected start of dependency link object but was {}","messagePattern":"Expected start of dependency link object but was (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"zipkin-storage/elasticsearch/src/main/java/zipkin2/elasticsearch/internal/JsonSerializers.java","lineNumber":190,"sourceCode":"          timestamp = parser.getLongValue();\n          break;\n        case \"value\":\n          value = parser.getValueAsString();\n          break;\n        default:\n          // Skip\n      }\n    }\n\n    if (timestamp == 0 || value == null) {\n      throw new IllegalArgumentException(\"Incomplete annotation at \" + parser.currentToken());\n    }\n    return Annotation.create(timestamp, value);\n  }\n\n  public static final ObjectParser<DependencyLink> DEPENDENCY_LINK_PARSER = parser -> {\n    if (!parser.isExpectedStartObjectToken()) {\n      throw new IllegalArgumentException(\"Expected start of dependency link object but was \"\n        + parser.currentToken());\n    }\n\n    DependencyLink.Builder result = DependencyLink.newBuilder();\n    JsonToken value;\n    while ((value = parser.nextValue()) != JsonToken.END_OBJECT) {\n      if (value == null) {\n        throw new IOException(\"End of input while parsing object.\");\n      }\n      switch (parser.currentName()) {\n        case \"parent\":\n          result.parent(parser.getText());\n          break;\n        case \"child\":\n          result.child(parser.getText());\n          break;\n        case \"callCount\":\n          result.callCount(parser.getLongValue());","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin-storage/elasticsearch/src/main/java/zipkin2/elasticsearch/internal/JsonSerializers.java#L172-L208","documentation":"DEPENDENCY_LINK_PARSER decodes each element of the dependency-link array returned by Elasticsearch and requires a JSON object start; any other token throws IllegalArgumentException('Expected start of dependency link object but was <token>'). Dependency links are read when getDependencies() aggregates the dependency indices.","triggerScenarios":"A document in a zipkin:dependency-* index whose top-level shape is not an object (array/scalar), or a converter feeding the parser at the wrong depth, when BodyConverters.DEPENDENCY_LINKS parses search hits.","commonSituations":"Custom jobs writing dependency data directly into Zipkin's dependency indices with wrong framing; corrupted index contents; version-skewed reads; tests with wrong fixtures.","solutions":["Inspect documents in the zipkin:dependency indices (GET <index>/_search) and confirm each hit _source is an object with parent/child/callCount.","Fix or remove whatever wrote malformed dependency documents.","Reindex/delete bad documents so getDependencies stops failing.","Use Zipkin's own DependencyLink store/serializer when producing links programmatically."],"exampleFix":"// before: dependency index doc _source = [\"frontend\",\"backend\",3]\n// -> IllegalArgumentException: Expected start of dependency link object but was START_ARRAY\n\n// after: _source = {\"parent\":\"frontend\",\"child\":\"backend\",\"callCount\":3}","handlingStrategy":"type-guard","validationCode":"var link = objectMapper.readTree(dependencyJson);\nif (!link.isObject()) {\n  throw new IOException(\"dependency link must be an object with parent/child/callCount\");\n}","typeGuard":"boolean dependencyLinkWellFormed(JsonNode n) {\n  return n.isObject() && n.has(\"parent\") && n.has(\"child\") && n.has(\"callCount\");\n}","tryCatchPattern":"try { DependencyLink l = DEPENDENCY_LINK_PARSER.parse(p); }\ncatch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Expected start of dependency link object\")) {\n    // malformed doc in dependency index: locate and reindex/delete it\n  }\n}","preventionTips":["Write dependency links only via Zipkin's DependencyLink serde (parent/child/callCount objects).","Periodically validate document shapes in zipkin:dependency indices if external jobs write to them.","Keep external writers out of Zipkin-managed indices."],"tags":["elasticsearch","json-parsing","dependency-link","schema","storage"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}