{"record":{"id":"5660873d35422808","repo":"apache/hadoop","slug":"byte-per-checksum-not-matched-bpc-but-bytesper-566087","errorCode":null,"errorMessage":"Byte-per-checksum not matched: bpc={} but bytesPerCRC={}","messagePattern":"Byte-per-checksum not matched: bpc=(.+?) but bytesPerCRC=(.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/FileChecksumHelper.java","lineNumber":385,"sourceCode":"    void extractChecksumProperties(\n        OpBlockChecksumResponseProto checksumData,\n        LocatedBlock locatedBlock,\n        DatanodeInfo datanode,\n        int blockIdx)\n        throws IOException {\n      //read byte-per-checksum\n      final int bpc = checksumData.getBytesPerCrc();\n      if (blockIdx == 0) { //first block\n        setBytesPerCRC(bpc);\n      } else if (bpc != getBytesPerCRC()) {\n        if (getBlockChecksumType() == BlockChecksumType.COMPOSITE_CRC) {\n          LOG.warn(\n              \"Current bytesPerCRC={} doesn't match next bpc={}, but \"\n              + \"continuing anyway because we're using COMPOSITE_CRC. \"\n              + \"If trying to preserve CHECKSUMTYPE, only the current \"\n              + \"bytesPerCRC will be preserved.\", getBytesPerCRC(), bpc);\n        } else {\n          throw new IOException(\"Byte-per-checksum not matched: bpc=\" + bpc\n              + \" but bytesPerCRC=\" + getBytesPerCRC());\n        }\n      }\n\n      //read crc-per-block\n      final long cpb = checksumData.getCrcPerBlock();\n      if (getLocatedBlocks().size() > 1 && blockIdx == 0) {\n        setCrcPerBlock(cpb);\n      }\n\n      // read crc-type\n      final DataChecksum.Type ct;\n      if (checksumData.hasCrcType()) {\n        ct = PBHelperClient.convert(checksumData.getCrcType());\n      } else {\n        LOG.debug(\"Retrieving checksum from an earlier-version DataNode: \" +\n            \"inferring checksum by reading first byte\");\n        ct = getClient().inferChecksumTypeByReading(locatedBlock, datanode);","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/FileChecksumHelper.java#L367-L403","documentation":"While computing an MD5MD5CRC file checksum, the client reads each block's checksum header and requires bytesPerCRC (io.bytes.per.checksum) to be identical across all blocks — the MD5-of-MD5s combination is only defined for uniform chunking. If a later block reports a different bpc than the first block and the mode is not COMPOSITE_CRC, it throws this IOException. COMPOSITE_CRC is specifically designed to tolerate varying bytesPerCRC, which is why the code just logs a warning and continues in that mode.","triggerScenarios":"getFileChecksum()/DistCp -crc over a file whose blocks were written with different io.bytes.per.checksum values — e.g., appended after the cluster/client checksum config changed, files created pre- and post-config-change, or concatenated files (hdfs dfs -concat) with heterogeneous chunk sizes; the first block fixes bytesPerCRC and a subsequent block disagrees.","commonSituations":"Appends to old files after io.bytes.per.checksum was changed; distcp between clusters with different checksum settings using -crc/-p checksum; verifying checksums of archived data written under legacy 512-byte settings vs newer custom values.","solutions":["Set dfs.checksum.combine.mode=COMPOSITE_CRC on the client (and both sides for distcp) — it supports differing bytesPerCRC by design","For distcp, drop checksum verification (-skip-checksum-difference) or use COMPOSITE_CRC on both clusters","Rewrite the file (hdfs dfs -get/-put, or distcp without -p checksum) to normalize all blocks to current checksum settings","Prevent recurrence: keep io.bytes.per.checksum stable for the lifetime of files that will be appended to"],"exampleFix":"<!-- before -->\n<property>\n  <name>dfs.checksum.combine.mode</name>\n  <value>MD5MD5CRC</value>\n</property>\n\n<!-- after: tolerate per-block bytesPerCRC differences -->\n<property>\n  <name>dfs.checksum.combine.mode</name>\n  <value>COMPOSITE_CRC</value>\n</property>","handlingStrategy":"fallback","validationCode":"// Before a checksum job over legacy data, check per-block checksum settings\n// via a probe read: compute checksum of a small range and on failure switch mode.\n// Simplest up-front guard: choose COMPOSITE_CRC when files may be heterogeneous.\nconf.set(\"dfs.checksum.combine.mode\", \"COMPOSITE_CRC\");","typeGuard":null,"tryCatchPattern":"try {\n  return fs.getFileChecksum(path); // MD5MD5CRC default\n} catch (IOException e) {\n  if (e.getMessage().contains(\"Byte-per-checksum not matched\")) {\n    conf.set(\"dfs.checksum.combine.mode\", \"COMPOSITE_CRC\");\n    return fs.getFileChecksum(path); // tolerant combine mode\n  }\n  throw e;\n}","preventionTips":["Standardize io.bytes.per.checksum cluster-wide and never append to files written under a different value without expecting checksum issues","For distcp -crc over historical data, set dfs.checksum.combine.mode=COMPOSITE_CRC on both ends","Expect legacy files to have 512-byte checksums; new files with custom values mixed via append will not verify under MD5MD5CRC"],"tags":["hdfs","checksum","file-integrity","configuration","distcp"],"backgroundTag":"checksum-mismatch","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}