{"record":{"id":"5f6705acc31b68ab","repo":"alibaba/canal","slug":"expected-length-of-at-least-bytes-but-had","errorCode":null,"errorMessage":"Expected length of at least {} bytes, but had {}","messagePattern":"Expected length of at least (.+?) bytes, but had (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"client-adapter/hbase/src/main/java/com/alibaba/otter/canal/client/adapter/hbase/support/PhTypeUtil.java","lineNumber":604,"sourceCode":"            result[--index] = (byte) (digit * multiplyBy + digitOffset);\n            multiplyBy = 1;\n            divideBy = ONE_HUNDRED;\n        }\n        long l = bi.longValue();\n        do {\n            long divBy = 100 / multiplyBy;\n            long digit = l % divBy;\n            l /= divBy;\n            result[--index] = (byte) (digit * multiplyBy + digitOffset);\n            multiplyBy = 1;\n        } while (l != 0);\n\n        return length;\n    }\n\n    private static void checkForSufficientLength(byte[] b, int offset, int requiredLength) {\n        if (b.length < offset + requiredLength) {\n            throw new RuntimeException(\n                \"Expected length of at least \" + requiredLength + \" bytes, but had \" + (b.length - offset));\n        }\n    }\n\n}\n","sourceCodeStart":586,"sourceCodeEnd":610,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/client-adapter/hbase/src/main/java/com/alibaba/otter/canal/client/adapter/hbase/support/PhTypeUtil.java#L586-L610","documentation":"PhTypeUtil.checkForSufficientLength() guards every PHOENIX-mode decode: it verifies the byte array is long enough to hold the required type at the given offset. When reading a value with the wrong PHOENIX PhType (or truncated/corrupt bytes), the array is shorter than the type demands and it throws a RuntimeException naming expected vs actual byte counts.","triggerScenarios":"Reading HBase cells in PHOENIX mode where the stored bytes were written with a different type than the configured PhType, or the byte array is truncated/corrupt; e.g. decoding 3 bytes as an INT (needs 4) or 7 bytes as a LONG (needs 8).","commonSituations":"Changing a column's configured PHOENIX type after data was already written with the old type; data corruption in HBase; a column type misconfiguration in the mapping; mode mismatch between write and read.","solutions":["Align the column's configured PHOENIX type with the type originally used to write the bytes (re-ETL if the type changed).","Verify the mapping 'columns' type annotation (the part after '$') matches the actual stored PHOENIX type.","Audit the HBase cell bytes for truncation/corruption.","If migrating types, do a full re-import (ETL) so all bytes use the new encoding."],"exampleFix":"# before (type mismatch after data written)\ncolumns:\n  amount: CF:amount$INTEGER\n\n# after (match the stored PHOENIX type)\ncolumns:\n  amount: CF:amount$DECIMAL","handlingStrategy":"validation","validationCode":"// Before decoding in PHOENIX mode, sanity-check byte length\nPhType ph = PhType.getType(columnItem.getType());\nint needed = expectedLengthFor(ph); // your helper mapping PhType->Bytes.SIZEOF_*\nif (bytes.length < needed) {\n    throw new IllegalStateException(\"byte length \" + bytes.length + \" < required \" + needed + \" for \" + ph);\n}","typeGuard":null,"tryCatchPattern":"try {\n    Object v = PhTypeUtil.toObject(bytes, phType);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Expected length\")) {\n        logger.error(\"Stored bytes shorter than PHOENIX type requires; likely a type change or corruption - re-ETL\");\n    }\n    throw e;\n}","preventionTips":["Keep each column's configured PHOENIX type stable; re-ETL after any type change.","Audit HBase cells for truncation/corruption after cluster incidents.","Verify the mapping type annotation matches the write-time encoding."],"tags":["hbase-adapter","phoenix","type-conversion","data-corruption"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}