{"record":{"id":"8c6509ea9d720ec1","repo":"apache/beam","slug":"invalid-encoded-byte-array","errorCode":null,"errorMessage":"Invalid encoded byte array","messagePattern":"Invalid encoded byte array","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/OrderedCode.java","lineNumber":383,"sourceCode":"  }\n\n  /**\n   * Returns the next byte array item from its encoded byte array store and removes the item from\n   * the store.\n   *\n   * @see #writeBytes(byte[])\n   */\n  public byte[] readBytes() {\n    return readBytes(false);\n  }\n\n  public byte[] readBytesDecreasing() {\n    return readBytes(true);\n  }\n\n  private byte[] readBytes(boolean invert) {\n    if (encodedArrays.isEmpty() || (encodedArrays.get(0).length - firstArrayPosition <= 0)) {\n      throw new IllegalArgumentException(\"Invalid encoded byte array\");\n    }\n\n    // Determine the length of the decoded array\n    // We only scan up to \"length-2\" since a valid string must end with\n    // a two character terminator: 'ESCAPE1 SEPARATOR'\n    byte[] store = encodedArrays.get(0);\n    int decodedLength = 0;\n    boolean valid = false;\n    int i = firstArrayPosition;\n    while (i < store.length - 1) {\n      byte b = store[i++];\n      if (b == convert(invert, ESCAPE1)) {\n        b = store[i++];\n        if (b == convert(invert, SEPARATOR)) {\n          valid = true;\n          break;\n        } else if (b == convert(invert, NULL_CHARACTER)) {\n          decodedLength++;","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/OrderedCode.java#L365-L401","documentation":"readBytes (and readBytesDecreasing) begins decoding the next segment from the internal encoded store. If the store is empty or the remaining bytes in the first array are exhausted (length - firstArrayPosition <= 0), the encoded stream is malformed or fully consumed, so it throws IllegalArgumentException(\"Invalid encoded byte array\").","triggerScenarios":"Calling readBytes/readBytesDecreasing more times than writeBytes was called, or decoding a buffer that was truncated/corrupted in transit, so nothing remains to read.","commonSituations":"Deserializing keys stored in an external system (Spanner keys, ordering keys) that were hand-trimmed, round-tripped through a different encoder, or sliced at wrong boundaries.","solutions":["Check hasRemainingEncodedBytes() before each read and stop when it returns false.","Ensure the byte array being decoded was produced entirely by the matching OrderedCode write methods without external modification.","Pair every read* call one-to-one with its write* call in the same order used at encode time."],"exampleFix":"// before\nbyte[] b = oc.readBytes();\n// after\nif (oc.hasRemainingEncodedBytes()) {\n  byte[] b = oc.readBytes();\n}","handlingStrategy":"try-catch","validationCode":"if (!oc.hasRemainingEncodedBytes()) { return null; /* or throw domain error */ }","typeGuard":null,"tryCatchPattern":"try { return oc.readBytes(); } catch (IllegalArgumentException e) { if (e.getMessage().equals(\"Invalid encoded byte array\")) { throw new CorruptKeyException(e); } throw e; }","preventionTips":["Check hasRemainingEncodedBytes() before each read","Never slice or re-encode OrderedCode output manually","Persist encoded keys as binary-safe values"],"tags":["java","orderedcode","decoding","corrupt-data"],"backgroundTag":"invalid-argument-format","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}