{"record":{"id":"e50e42c487d0e0fc","repo":"tursodatabase/turso","slug":"setobject-does-not-yet-support-lob-or-stream-types","errorCode":null,"errorMessage":"setObject does not yet support LOB or Stream types because the corresponding set methods are unimplemented. Type found: {type}","messagePattern":"setObject does not yet support LOB or Stream types because the corresponding set methods are unimplemented\\. Type found: (.+?)","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java","lineNumber":311,"sourceCode":"    } else if (x instanceof Byte) {\n      setByte(parameterIndex, (Byte) x);\n    } else if (x instanceof Short) {\n      setShort(parameterIndex, (Short) x);\n    } else if (x instanceof byte[]) {\n      setBytes(parameterIndex, (byte[]) x);\n    } else if (x instanceof Timestamp) {\n      setTimestamp(parameterIndex, (Timestamp) x);\n    } else if (x instanceof Date) {\n      setDate(parameterIndex, (Date) x);\n    } else if (x instanceof Time) {\n      setTime(parameterIndex, (Time) x);\n    } else if (x instanceof BigDecimal) {\n      setBigDecimal(parameterIndex, (BigDecimal) x);\n    } else if (x instanceof Blob\n        || x instanceof Clob\n        || x instanceof InputStream\n        || x instanceof Reader) {\n      throw new SQLException(\n          \"setObject does not yet support LOB or Stream types because the corresponding set methods are unimplemented. Type found: \"\n              + x.getClass().getName());\n    } else {\n      throw new SQLException(\"Unsupported object type in setObject: \" + x.getClass().getName());\n    }\n  }\n\n  @Override\n  public boolean execute() throws SQLException {\n    return execute(currentBatchParams);\n  }\n\n  /** This helper method runs the statement using the provided parameter values. */\n  private boolean execute(Object[] params) throws SQLException {\n    // TODO: check whether this is sufficient\n    requireNonNull(statement);\n    bindParams(params);\n    boolean result = statement.execute();","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java#L293-L329","documentation":"setObject(int, Object) in this driver supports only scalar types (null, String, Integer, Long, Boolean, Double, Float, Byte, Short, byte[], Timestamp, java.sql.Date, Time, BigDecimal). Blob, Clob, InputStream and Reader are explicitly rejected because their dedicated setters (setBlob, setClob, ...) are still unimplemented TODO stubs in JDBC4PreparedStatement, so the driver throws rather than silently no-op. The offending class name is appended to the message.","triggerScenarios":"ps.setObject(i, blob), ps.setObject(i, clob), ps.setObject(i, inputStream), or ps.setObject(i, reader); ORMs and generic repository layers that funnel every value through setObject.","commonSituations":"Spring/Hibernate-style generic binders; code ported from PostgreSQL/MySQL drivers whose setObject accepted streams and LOBs; file-upload code wrapping payloads as InputStream for a 'bind anything' helper.","solutions":["Materialize the value and use a supported setter: Blob -> ps.setBytes(i, blob.getBytes(1, (int) blob.length())); Clob -> ps.setString(i, clob.getSubString(1, (int) clob.length())).","For streams call the implemented dedicated overloads directly: setBinaryStream(i, in) or setCharacterStream(i, reader) instead of setObject.","In generic layers, normalize InputStream/Reader/Blob/Clob to byte[]/String before setObject (see type guard)."],"exampleFix":"// before\nps.setObject(1, new ByteArrayInputStream(data)); // throws\n\n// after\nps.setBinaryStream(1, new ByteArrayInputStream(data));\n// or simply\nps.setBytes(1, data);","handlingStrategy":"type-guard","validationCode":"Object v = normalizeForSetObject(raw); // InputStream/Reader -> materialize; Blob -> getBytes; Clob -> getSubString\nps.setObject(i, v);","typeGuard":"static boolean isSetObjectLobOrStream(Object x) {\n    return x instanceof java.sql.Blob || x instanceof java.sql.Clob\n        || x instanceof InputStream || x instanceof Reader;\n}","tryCatchPattern":"catch (SQLException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"setObject does not yet support\")) {\n        // driver limitation: convert the named class to byte[]/String and rebind\n    }\n    throw e;\n}","preventionTips":["Never hand LOB/stream objects to setObject with this driver; bind via dedicated setters.","Beware: setBlob(int, Blob), setClob, setRef and setObject(int, Object, int) are silent TODO stubs — binding through them no-ops, so cover them with tests.","Add the normalize step once in your generic DAO layer, not at each call site."],"tags":["jdbc","setobject","lob","stream","unimplemented"],"backgroundTag":"unsupported-type-conversion","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}