{"record":{"id":"e904d6c0f2479898","repo":"apache/shardingsphere","slug":"failed-to-read-java-sql-blob-content","errorCode":null,"errorMessage":"Failed to read java.sql.Blob content","messagePattern":"Failed to read java\\.sql\\.Blob content","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/packet/command/query/statement/execute/protocol/FirebirdBlobBinaryProtocolValue.java","lineNumber":107,"sourceCode":"    }\n    \n    @Override\n    public void write(final FirebirdPacketPayload payload, final Object value) {\n        long blobId;\n        \n        if (null == value) {\n            blobId = 0L;\n        } else if (value instanceof Long) {\n            blobId = (Long) value;\n        } else if (value instanceof byte[]) {\n            blobId = register(payload.getConnectionId(), (byte[]) value);\n        } else if (value instanceof Blob) {\n            try {\n                blobId = register(payload.getConnectionId(), readAllBytes(((Blob) value).getBinaryStream()));\n            } catch (final SQLException ex) {\n                throw new IllegalStateException(\"Failed to read java.sql.Blob stream\", ex);\n            } catch (final IOException ex) {\n                throw new IllegalStateException(\"Failed to read java.sql.Blob content\", ex);\n            }\n        } else if (value instanceof Clob) {\n            try {\n                Clob clob = (Clob) value;\n                int len = (int) Math.min(Integer.MAX_VALUE, clob.length());\n                String str = clob.getSubString(1L, len);\n                blobId = register(payload.getConnectionId(), str.getBytes(payload.getCharset()));\n            } catch (final SQLException ex) {\n                throw new IllegalStateException(\"Failed to read java.sql.Clob\", ex);\n            }\n        } else {\n            blobId = register(payload.getConnectionId(), value.toString().getBytes(payload.getCharset()));\n        }\n        \n        payload.writeInt8(blobId);\n    }\n    \n    @Override","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/packet/command/query/statement/execute/protocol/FirebirdBlobBinaryProtocolValue.java#L89-L125","documentation":"Thrown while reading the contents of a java.sql.Blob parameter for the Firebird wire protocol: the binary stream was opened successfully, but reading it raised IOException (the sibling SQLException path produces 'Failed to read java.sql.Blob stream'). The original IOException is chained. Typical causes are an interrupted/closed stream or a LOB whose underlying storage vanished mid-read.","triggerScenarios":"Passing a java.sql.Blob whose getBinaryStream() returns a stream that fails during readAllBytes() — e.g. the LOB buffer was freed, the socket to the backing store dropped, or a custom Blob implementation throws IOException from read().","commonSituations":"Custom Blob implementations wrapping files/network streams where the source becomes unavailable; database-side temp-LOBs invalidated by transaction end; large BLOBs whose read crosses a driver buffer timeout.","solutions":["Inspect the chained IOException for the true I/O failure (file closed, socket reset, buffer freed)","If the Blob is driver-backed, keep its transaction open until after parameter binding completes","Materialize the bytes up front and bind with setBytes() to eliminate the streaming path","For custom Blob classes, verify getBinaryStream() returns a fully readable, open stream"],"exampleFix":"// before: streaming Blob whose source may vanish mid-read\nps.setBlob(1, maybeBrokenBlob);\n\n// after: read eagerly while the source is still valid, then bind bytes\nbyte[] bytes = readAllBytes(maybeBrokenBlob.getBinaryStream()); // handle errors at your boundary\nps.setBytes(1, bytes);","handlingStrategy":"try-catch","validationCode":"// drain the Blob stream eagerly inside your own error boundary before binding\nbyte[] bytes;\ntry (InputStream in = blob.getBinaryStream()) {\n    bytes = in.readAllBytes();\n} catch (IOException | SQLException ex) {\n    throw new IllegalArgumentException(\"blob source unreadable\", ex);\n}\nps.setBytes(1, bytes); // no streaming path left to fail inside the protocol writer","typeGuard":null,"tryCatchPattern":"try {\n    ps.setBlob(1, blob);\n} catch (IllegalStateException ex) {\n    if (ex.getCause() instanceof IOException) {\n        // underlying stream failed: retry once from the materialized copy if you kept one\n        ps.setBytes(1, cachedBytes);\n    } else {\n        throw ex;\n    }\n}","preventionTips":["Materialize LOB content to byte[] at your boundary so I/O failures surface in your own error handling","For custom Blob implementations, keep the backing resource open until execution completes"],"tags":["firebird","jdbc","blob","io","serialization"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}