t8y2/dbx · error · SQLException

Failed to read CLOB value

Error message

Failed to read CLOB value

What it means

When reading a ResultSet value that is a Clob, the plugin streams it into a String; any IOException raised by Clob.getCharacterStream() is wrapped in a SQLException with message "Failed to read CLOB value" and the original cause attached. This indicates the large-character data could not be read from the driver, often after the connection/statement state was invalidated.

Source

Thrown at plugins/jdbc/src/main/java/app/dbx/jdbc/DbxJdbcPlugin.java:4335

            return decimal;
        }
        if (value instanceof Number || value instanceof Boolean || value instanceof String) {
            return value;
        }
        return value.toString();
    }

    private static String clobToString(Clob clob) throws SQLException {
        try (Reader reader = clob.getCharacterStream()) {
            StringBuilder out = new StringBuilder();
            char[] buffer = new char[8192];
            int count;
            while ((count = reader.read(buffer)) != -1) {
                out.append(buffer, 0, count);
            }
            return out.toString();
        } catch (IOException error) {
            throw new SQLException("Failed to read CLOB value", error);
        }
    }

    private static Object readTemporalValue(
        ResultSet rs,
        ResultSetMetaData meta,
        int index,
        boolean preserveOracleDateTime,
        ZoneId timestampZone
    ) throws SQLException {
        return switch (meta.getColumnType(index)) {
            case Types.DATE -> {
                if (preserveOracleDateTime) {
                    Timestamp timestamp = rs.getTimestamp(index);
                    yield timestamp == null ? null : timestamp.toString();
                }
                Date date = rs.getDate(index);
                yield date == null ? null : date.toString();

View on GitHub (pinned to c0390bff16)

Solutions

  1. Check the wrapped cause (error.getCause()) to identify the driver-level failure
  2. Re-run the query and read the row again (transient network issues)
  3. Reduce the number/size of CLOB columns fetched or paginate the query
  4. Ensure the CLOB is fully consumed before advancing the ResultSet; upgrade/patch the JDBC driver
  5. Increase connection/socket timeouts for large text columns

Example fix

// before
rs.next(); String a = rs.getString(1); String clobText = pluginReadClob(rs.getClob(2)); // LOB freed by some drivers after next()
// after
rs.next(); String clobText = pluginReadClob(rs.getClob(2)); String a = rs.getString(1); // read CLOB before moving on
Defensive patterns

Strategy: retry

Validate before calling

// Before reading, verify the LOB is live and the connection is open:
if (clob == null) return null;
if (connection.isClosed() || rs.isClosed()) {
    throw new IllegalStateException("Connection/ResultSet closed before CLOB read");
}

Type guard

boolean isReadable(Clob clob) {
    try { return clob != null && clob.length() >= 0; } catch (SQLException e) { return false; }
}

Try / catch

try {
    return readClob(rs.getClob(col));
} catch (SQLException e) {
    if (e.getMessage().startsWith("Failed to read CLOB value")) {
        // re-execute query and retry once; log e.getCause() for the driver-level reason
    } else throw e;
}

Prevention

When it happens

Trigger: Calling nextRow/fetch on a result set containing CLOB/TEXT columns when the underlying stream fails — e.g. connection dropped mid-read, driver freed the LOB after the row cursor moved, or an encoding/stream error in the JDBC driver.

Common situations: Network interruption while streaming a large text column; drivers that invalidate LOBs once ResultSet.next() advances; fetching very large CLOBs that exceed driver memory/stream limits; connection timeout during read.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/4a4a59d841ad3912. Report an issue: GitHub.