{"record":{"id":"7006d653998b31e1","repo":"hibernate/hibernate-orm","slug":"underlying-stream-does-not-allow-reset","errorCode":null,"errorMessage":"Underlying stream does not allow reset","messagePattern":"Underlying stream does not allow reset","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/BlobProxy.java","lineNumber":98,"sourceCode":"\t\t}\n\t}\n\n\tprivate InputStream getStream() throws SQLException {\n\t\treturn getUnderlyingStream().getInputStream();\n\t}\n\n\t@Override\n\tpublic BinaryStream getUnderlyingStream() throws SQLException {\n\t\tresetIfNeeded();\n\t\treturn binaryStream;\n\t}\n\n\tprivate void resetIfNeeded() throws SQLException {\n\t\ttry {\n\t\t\tif ( needsReset ) {\n\t\t\t\tfinal InputStream inputStream = binaryStream.getInputStream();\n\t\t\t\tif ( !resetAllowed && inputStream != null) {\n\t\t\t\t\tthrow new SQLException( \"Underlying stream does not allow reset\" );\n\t\t\t\t}\n\t\t\t\tif ( inputStream != null ) {\n\t\t\t\t\tinputStream.reset();\n\t\t\t\t\tsetStreamMark();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch ( IOException ioe) {\n\t\t\tthrow new SQLException(\"could not reset reader\");\n\t\t}\n\t\tneedsReset = true;\n\t}\n\n\t/**\n\t * Generates a BlobImpl using byte data.\n\t *\n\t * @param bytes The data to be created as a Blob.\n\t *","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/BlobProxy.java#L80-L116","documentation":"BlobProxy wraps a stream-backed Blob created via generateProxy(InputStream, length). After the stream has been read once (needsReset), later access goes through resetIfNeeded(), which rewinds the stream with InputStream.reset(). resetAllowed is only true when the stream supported mark/reset at construction (markSupported()); otherwise it throws SQLException('Underlying stream does not allow reset').","triggerScenarios":"Creating a Blob from an InputStream that does not support mark/reset (raw socket stream, some compression/DB LOB streams) via Hibernate.getLobHelper().createBlob(stream, length), then reading the Blob more than once — e.g. the driver reads it to send data and Hibernate/driver reads it again for length or logging.","commonSituations":"Streaming uploads straight from sockets or crypto/compression streams into Blob fields; drivers that consume the Blob twice (statement logging, p6spy, replication); re-reading a materialized proxy after a failed statement.","solutions":["Wrap the stream in a mark/reset-capable stream first, e.g. new BufferedInputStream(in) (buffered when reasonably small) — or read all bytes and use createBlob(byte[])","Ensure the Blob content is read only once, or buffer it fully in memory for large-object handling","Prefer byte[]- or String-backed LOBs when the source stream cannot be re-read"],"exampleFix":"// before: stream that cannot reset\nBlob b = session.getLobHelper().createBlob(socketStream, len);\n\n// after: mark/reset capable or fully materialized\nBlob b = session.getLobHelper().createBlob(new BufferedInputStream(socketStream), len);\n// or: Blob b = session.getLobHelper().createBlob(socketStream.readAllBytes());","handlingStrategy":"validation","validationCode":"// only hand reset-capable streams to createBlob\nInputStream in = rawStream.markSupported() ? rawStream : new BufferedInputStream(rawStream);\nBlob b = session.getLobHelper().createBlob(in, length);","typeGuard":"static boolean blobResetSafe(InputStream in) {\n    return in == null || in.markSupported();\n}","tryCatchPattern":null,"preventionTips":["Wrap non-markable streams in BufferedInputStream before createBlob(stream, len)","Prefer byte[]-backed Blobs when content fits in memory","Avoid drivers/proxies that read a Blob twice, or buffer fully"],"tags":["blob","stream","mark-reset","lob","hibernate"],"backgroundTag":"stream-mark-reset-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}