{"record":{"id":"dc62b27e28c5562b","repo":"hibernate/hibernate-orm","slug":"unable-to-access-lob-stream-dc62b2","errorCode":null,"errorMessage":"Unable to access lob stream","messagePattern":"Unable to access lob stream","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DataHelper.java","lineNumber":261,"sourceCode":"\t}\n\n\t/**\n\t * Extract the contents of the given Clob as a string.\n\t *\n\t * @param value The clob to to be extracted from\n\t *\n\t * @return The content as string\n\t */\n\tpublic static String extractString(final Clob value) {\n\t\ttry {\n\t\t\tfinal var characterStream = value.getCharacterStream();\n\t\t\tfinal long length = determineLengthForBufferSizing( value );\n\t\t\treturn length > Integer.MAX_VALUE\n\t\t\t\t\t? extractString( characterStream, Integer.MAX_VALUE )\n\t\t\t\t\t: extractString( characterStream, (int) length );\n\t\t}\n\t\tcatch ( SQLException e ) {\n\t\t\tthrow new HibernateException( \"Unable to access lob stream\", e );\n\t\t}\n\t}\n\n\t/**\n\t * Determine a buffer size for reading the underlying character stream.\n\t *\n\t * @param value The Clob value\n\t *\n\t * @return The appropriate buffer size ({@link Clob#length()} by default.\n\t *\n\t */\n\tprivate static long determineLengthForBufferSizing(Clob value) throws SQLException {\n\t\ttry {\n\t\t\treturn value.length();\n\t\t}\n\t\tcatch ( SQLFeatureNotSupportedException e ) {\n\t\t\treturn BUFFER_SIZE;\n\t\t}","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DataHelper.java#L243-L279","documentation":"DataHelper.extractString(Clob) opens value.getCharacterStream() and asks the Clob for its length (determineLengthForBufferSizing, backed by Clob.length()); any SQLException from those calls is wrapped as HibernateException('Unable to access lob stream'). This fails before a single character is read — the driver refused to hand out or measure the LOB.","triggerScenarios":"Clob.getCharacterStream() or Clob.length() throwing: the LOB was already freed or closed (Oracle frees temporary LOBs at transaction end), the connection is closed, something called Clob.free() prematurely, or the driver's Clob implementation does not support the call.","commonSituations":"Detached entities or web requests carrying Clob objects across transaction boundaries; proxying or wrapping JDBC objects; keeping Clob references in caches or HTTP sessions.","solutions":["Convert the Clob to String while the connection and transaction are alive — materialize before detaching","Never hold Clob objects in long-lived state; store the extracted String instead","Check that nothing (code, pool wrapper, driver) called Clob.free() before the read","Upgrade the JDBC driver if its Clob implementation lacks stream support"],"exampleFix":"// before\nClob c = rs.getClob(1);\n// ... later, after tx commit\nString s = extractText(c); // SQLException -> Unable to access lob stream\n\n// after\nClob c = rs.getClob(1);\nString s = c.getSubString(1, (int) c.length()); // materialize immediately, detach the String","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    String s = DataHelper.extractString(clob);\n} catch (HibernateException e) {\n    if (e.getCause() instanceof SQLException se) {\n        // lob freed/closed or connection gone: re-fetch the row in a fresh tx\n    }\n}","preventionTips":["Materialize LOBs to String/byte[] before detaching entities","Never call Clob.free() while Hibernate may still read it","Keep LOB reads inside the owning transaction"],"tags":["hibernate","lob","clob","jdbc","sqlexception"],"backgroundTag":"jdbc-lob-access-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}