{"record":{"id":"8c91daf49b3aabc0","repo":"apache/hadoop","slug":"data-at-path-too-short","errorCode":null,"errorMessage":"Data at path too short","messagePattern":"Data at path too short","errorType":"exception","errorClass":"NoRecordException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/binding/JsonSerDeser.java","lineNumber":103,"sourceCode":"   * @param path path the data came from\n   * @param bytes byte array\n   * @param marker an optional string which, if set, MUST be present in the\n   * UTF-8 parsed payload.\n   * @return The parsed record\n   * @throws IOException all problems\n   * @throws EOFException not enough data\n   * @throws InvalidRecordException if the JSON parsing failed.\n   * @throws NoRecordException if the data is not considered a record: either\n   * it is too short or it did not contain the marker string.\n   */\n  public T fromBytes(String path, byte[] bytes, String marker)\n      throws IOException {\n    int len = bytes.length;\n    if (len == 0 ) {\n      throw new NoRecordException(path, E_NO_DATA);\n    }\n    if (StringUtils.isNotEmpty(marker) && len < marker.length()) {\n      throw new NoRecordException(path, E_DATA_TOO_SHORT);\n    }\n    String json = new String(bytes, 0, len, StandardCharsets.UTF_8);\n    if (StringUtils.isNotEmpty(marker)\n        && !json.contains(marker)) {\n      throw new NoRecordException(path, E_MISSING_MARKER_STRING + marker);\n    }\n    try {\n      return fromJson(json);\n    } catch (JsonProcessingException e) {\n      throw new InvalidRecordException(path, e.toString(), e);\n    }\n  }\n\n}\n","sourceCodeStart":85,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/binding/JsonSerDeser.java#L85-L118","documentation":"fromBytes(path, bytes, marker) requires the payload to be at least as long as the expected marker string (for registry ServiceRecords the marker is 'JSONServiceRecord'). A non-empty payload shorter than the marker cannot possibly be a record, so it throws NoRecordException with 'Data at path too short'.","triggerScenarios":"A znode holding a few bytes of non-record data — an epoch counter, a flag like '1', leftover test data — being read as a ServiceRecord; or a truncated write from a publisher that crashed mid-operation.","commonSituations":"Mixing record nodes and plain utility nodes under the same registry subtree; partial writes after connection loss to ZooKeeper; manual znode edits with short placeholder values.","solutions":["Store plain values (counters, flags) in a separate subtree and never read them through fromBytes with a marker","Rewrite the node with a complete marshalled record (JsonSerDeser.toBytes) rather than patching bytes by hand","Guard reads by size: skip nodes whose stat.size is not greater than the marker length (RegistryUtils checks stat.size > ServiceRecord.RECORD_TYPE.length())"],"exampleFix":"// before\nServiceRecord r = marshal.fromBytes(path, zkGetData(path), ServiceRecord.RECORD_TYPE); // node holds \"1\"\n\n// after\nStat s = registryOps.stat(path);\nif (s == null || s.getDataLength() <= ServiceRecord.RECORD_TYPE.length()) {\n  return Optional.empty(); // not a record node\n}\nServiceRecord r = marshal.fromBytes(path, zkGetData(path), ServiceRecord.RECORD_TYPE);","handlingStrategy":"validation","validationCode":"Stat stat = registryOps.stat(path);\nif (stat == null || stat.getDataLength() <= marker.length()) {\n  return Optional.empty(); // too short to be a record — same guard RegistryUtils uses\n}\nreturn Optional.of(marshal.fromBytes(path, zkGetData(path), marker));","typeGuard":null,"tryCatchPattern":"try {\n  return Optional.of(marshal.fromBytes(path, bytes, marker));\n} catch (NoRecordException e) {\n  return Optional.empty(); // covers 'Data at path too short'\n}","preventionTips":["Never store counters/flags in nodes that will be read as records — use a separate subtree","Write records in one atomic ZooKeeper operation so truncation cannot occur","Use RegistryUtils-style size guards (stat.size > marker length) before record reads"],"tags":["registry","zookeeper","serialization","truncated-data"],"backgroundTag":"truncated-data","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}