{"record":{"id":"d4e52ca7fe16c7a4","repo":"apache/hadoop","slug":"wrong-header-string-header","errorCode":null,"errorMessage":"Wrong header string: \\\"\" + header + \"\\\"","messagePattern":"Wrong header string: \\\\\"\" \\+ header \\+ \"\\\\\"","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/impl/S3AMultipartUploader.java","lineNumber":320,"sourceCode":"        .toBytes();\n  }\n\n  /**\n   * Parse the payload marshalled as a part handle.\n   * @param data handle data\n   * @return the length and etag\n   * @throws IOException error reading the payload\n   */\n  @VisibleForTesting\n  static PartHandlePayload parsePartHandlePayload(\n      final byte[] data)\n      throws IOException {\n\n    try (DataInputStream input =\n             new DataInputStream(new ByteArrayInputStream(data))) {\n      final String header = input.readUTF();\n      if (!HEADER.equals(header)) {\n        throw new IOException(\"Wrong header string: \\\"\" + header + \"\\\"\");\n      }\n      final String path = input.readUTF();\n      final String uploadId = input.readUTF();\n      final int partNumber = input.readInt();\n      final long len = input.readLong();\n      final String etag = input.readUTF();\n      String checksumAlgorithm = null;\n      String checksum = null;\n      if (input.available() > 0) {\n        checksumAlgorithm = input.readUTF();\n        checksum = input.readUTF();\n      }\n      if (len < 0) {\n        throw new IOException(\"Negative length\");\n      }\n      return new PartHandlePayload(path, uploadId, partNumber, len, etag, checksumAlgorithm,\n          checksum);\n    }","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/impl/S3AMultipartUploader.java#L302-L338","documentation":"S3AMultipartUploader serializes each PartHandle as a DataOutputStream payload beginning with a magic header string (\"S3A-part01\", S3AMultipartUploader.HEADER). parsePartHandlePayload() deserializes it during MultipartUploader.complete() and throws a plain IOException if the first UTF field is anything else. It is a format guard: the byte[] you passed as a part handle was not produced by this serializer.","triggerScenarios":"Calling MultipartUploader.complete() with a byte[] PartHandle from a different filesystem implementation or a different MultipartUploader; handles persisted from another (older/newer) Hadoop version whose payload format changed; manually constructed or truncated handle bytes; base64/encoding round-trip that corrupted the bytes.","commonSituations":"Applications persisting PartHandles between jobs (e.g. writing them to a file or store and completing later across a Hadoop upgrade); mixing handles obtained from different FileSystem instances (one S3A, one wrapped/filtered or emulated); corrupted handle blobs in a queue/database.","solutions":["Use only PartHandle byte arrays returned by upload() on the same S3A MultipartUploader session, passed unchanged to complete().","If handles were persisted before a Hadoop upgrade, discard them, abort the uploads, and restart the upload from scratch on the current version.","Verify the byte[] was not re-encoded (no String round-trips with non-ISO-8859-1 charsets, no truncation) when you store it.","Catch IOException around complete() and fall back to abort() + full re-upload of the part."],"exampleFix":"// before: completing with a handle of unknown provenance\npartUploader.complete(destinationPath, uploadId, Arrays.asList(unknownPartHandle));\n\n// after: validate provenance, then fall back on parse failure\ntry {\n  partUploader.complete(destinationPath, uploadId, partsFromSameUpload);\n} catch (IOException e) {\n  partUploader.abort(uploadId);\n  // re-upload the part with the current uploader and retry complete()\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  multipartUploader.complete(destPath, uploadHandle, partHandles);\n} catch (IOException e) {\n  // bad serialized part handle: abort session, re-upload parts, complete again\n  multipartUploader.abort(uploadHandle);\n  restartUploadFromSource();\n}","preventionTips":["Treat PartHandle byte arrays as opaque: never persist them across versions, never reconstruct them.","Complete uploads in the same job and Hadoop version that created the handles.","Pass handles through verbatim (no String/charset round-trips, no truncation)."],"tags":["hadoop-aws","multipart-uploader","part-handle","serialization","data-corruption"],"backgroundTag":"invalid-serialized-handle","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}