{"record":{"id":"b5031598f3f23140","repo":"hibernate/hibernate-orm","slug":"ioexception-occurred-reading-a-binary-value","errorCode":null,"errorMessage":"IOException occurred reading a binary value","messagePattern":"IOException occurred reading a binary value","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StreamBackedBinaryStream.java","lineNumber":43,"sourceCode":"\n\tpublic StreamBackedBinaryStream(InputStream stream, long length) {\n\t\tthis.stream = stream;\n\t\tthis.length = length;\n\t}\n\n\t@Override\n\tpublic InputStream getInputStream() {\n\t\treturn stream;\n\t}\n\n\t@Override\n\tpublic byte[] getBytes() {\n\t\tif ( bytes == null ) {\n\t\t\ttry {\n\t\t\t\tbytes = stream.readAllBytes();\n\t\t\t}\n\t\t\tcatch (IOException e) {\n\t\t\t\tthrow new HibernateException( \"IOException occurred reading a binary value\", e );\n\t\t\t}\n\t\t}\n\t\treturn bytes;\n\t}\n\n\t@Override\n\tpublic long getLength() {\n\t\treturn length;\n\t}\n\n\t@Override\n\tpublic Blob asBlob(LobCreator lobCreator) {\n\t\treturn lobCreator.createBlob( stream, length );\n\t}\n\n\t@Override\n\tpublic void release() {\n\t\ttry {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StreamBackedBinaryStream.java#L25-L61","documentation":"StreamBackedBinaryStream.getBytes() lazily materializes the wrapped InputStream with readAllBytes() the first time the byte[] is needed (e.g. when binding a stream-backed Blob to a statement). An IOException during that read is wrapped in HibernateException('IOException occurred reading a binary value').","triggerScenarios":"A Blob/binary value created from an InputStream (e.g. Hibernate.getLobHelper().createBlob(stream, length)) whose underlying stream is already consumed, closed, or fails when Hibernate finally reads it at flush/bind time.","commonSituations":"Reading the provided InputStream yourself before handing it to Hibernate; streams over files/sockets/LOB locators that are closed between entity update and flush; deferred flushes after the stream source went away.","solutions":["Do not consume the InputStream before/after giving it to Hibernate; treat it as owned by Hibernate","Read the bytes into a byte[] first and create the Blob from the array if the source cannot stay open until flush","Keep the stream and its resource (file/connection) open until the transaction commits"],"exampleFix":"// before: stream may be closed by the time Hibernate reads it\nentity.setAttachment(lobHelper.createBlob(socketStream, len));\n\n// after: materialize up front\nbyte[] bytes = socketStream.readAllBytes();\nentity.setAttachment(lobHelper.createBlob(bytes));","handlingStrategy":"validation","validationCode":"// ensure the stream is fully readable before handing it over\nif (!stream.markSupported()) { /* wrap or materialize */ }\nbyte[] bytes = stream.readAllBytes(); // materialize once, up front\nentity.setAttachment(lobHelper.createBlob(bytes));","typeGuard":null,"tryCatchPattern":"try {\n    session.flush();\n}\ncatch (HibernateException e) {\n    if (e.getCause() instanceof java.io.IOException io) {\n        // the backing stream failed: re-open source and rebind a materialized value\n    }\n}","preventionTips":["Never read/close the InputStream you pass to createBlob","Materialize byte[] when the source cannot stay open until commit","Bind stream-backed LOBs late, close to flush time"],"tags":["io","binary","blob","stream","hibernate"],"backgroundTag":"blob-stream-read-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}