{"record":{"id":"736bc3649cdd6baa","repo":"hibernate/hibernate-orm","slug":"can-t-deal-with-blobs-larger-than-integer-max-val","errorCode":null,"errorMessage":"Can't deal with Blobs larger than 'Integer.MAX_VALUE'","messagePattern":"Can't deal with Blobs larger than 'Integer\\.MAX_VALUE'","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/BlobProxy.java","lineNumber":205,"sourceCode":"\tpublic void truncate(long len) {\n\t\tthrow notSupported();\n\t}\n\n\t@Override\n\tpublic void free() {\n\t\tbinaryStream.release();\n\t}\n\n\t@Override\n\tpublic InputStream getBinaryStream(final long start, final long length) throws SQLException {\n\t\tif ( start < 1 ) {\n\t\t\tthrow new SQLException( \"Start position 1-based; must be 1 or more.\" );\n\t\t}\n\t\tif ( start > length() ) {\n\t\t\tthrow new SQLException( \"Start position [\" + start + \"] cannot exceed overall CLOB length [\" + length() + \"]\" );\n\t\t}\n\t\tif ( length > Integer.MAX_VALUE ) {\n\t\t\tthrow new SQLException( \"Can't deal with Blobs larger than 'Integer.MAX_VALUE'\" );\n\t\t}\n\t\tif ( length < 0 ) {\n\t\t\t// javadoc for getBinaryStream(long,int) specifies that the start+length must not exceed the\n\t\t\t// total length (this is at odds with the behavior of getBytes(long,int))\n\t\t\tthrow new SQLException( \"Length must be great-than-or-equal to zero.\" );\n\t\t}\n\t\treturn DataHelper.subStream( getStream(), start-1, (int)length );\n\t}\n\n\tprivate static UnsupportedOperationException notSupported() {\n\t\treturn new UnsupportedOperationException( \"Blob may not be manipulated from creating session\" );\n\t}\n\n}\n","sourceCodeStart":187,"sourceCodeEnd":220,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/BlobProxy.java#L187-L220","documentation":"BlobProxy.getBinaryStream(long start, long length) can only produce a sub-stream whose length fits an int, because it ultimately casts length to int for DataHelper.subStream. A length argument above Integer.MAX_VALUE is rejected with this SQLException rather than being silently truncated.","triggerScenarios":"Calling blob.getBinaryStream(1, blob.length()) when the blob exceeds Integer.MAX_VALUE bytes; passing Long.MAX_VALUE as an 'until the end' marker; generic copy utilities that forward a user-supplied long maxSize.","commonSituations":"Multi-GB LOBs (video, genomics, backups) stored in databases with huge-lob support; helper APIs that accept long sizes from HTTP Range headers; migrating from drivers that clamp silently to Hibernate's proxy which fails fast.","solutions":["Read in chunks: loop with length capped at e.g. 8 MB per call","For whole-stream access use getBinaryStream() (no args) and stream-copy instead of fixed windows","Replace 'read all' sentinels like Long.MAX_VALUE with the real remaining length"],"exampleFix":"// before\nInputStream all = blob.getBinaryStream(1, Long.MAX_VALUE); // throws\n\n// after\nInputStream all = blob.getBinaryStream(); // full stream, copy incrementally","handlingStrategy":"validation","validationCode":"static final long MAX_WINDOW = 8L * 1024 * 1024; // 8 MiB per call\nstatic long cappedWindow(long requested, long remaining) {\n    if (requested < 0) throw new IllegalArgumentException(\"length must be >= 0\");\n    return Math.min(Math.min(requested, remaining), MAX_WINDOW);\n}\n// usage: blob.getBinaryStream(start, cappedWindow(len, blob.length() - start + 1))","typeGuard":null,"tryCatchPattern":"try {\n    in = blob.getBinaryStream(start, length);\n} catch (SQLException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Integer.MAX_VALUE\")) {\n        in = blob.getBinaryStream();                 // fall back to the full stream\n    } else {\n        throw e;\n    }\n}","preventionTips":["Never pass Long.MAX_VALUE or blob.length() of a multi-GB LOB as the window size","Cap every positioned read at a few MiB and loop","Use the no-arg getBinaryStream() plus incremental copy for whole-content access"],"tags":["hibernate","jdbc","blob","lob","integer-overflow","large-objects","sql-exception"],"backgroundTag":"jdbc-lob-exceeds-max-int","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}