{"record":{"id":"f9f7f9e80b74595a","repo":"tursodatabase/turso","slug":"error-reading-character-stream","errorCode":null,"errorMessage":"Error reading character stream","messagePattern":"Error reading character stream","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java","lineNumber":424,"sourceCode":"    }\n    if (length < 0) {\n      throw new SQLException(\"setCharacterStream length must be non-negative\");\n    }\n    if (length == 0) {\n      setParam(parameterIndex, \"\");\n      return;\n    }\n    try {\n      char[] buffer = new char[length];\n      int offset = 0;\n      int read;\n      while (offset < length && (read = reader.read(buffer, offset, length - offset)) > 0) {\n        offset += read;\n      }\n      String value = new String(buffer, 0, offset);\n      setParam(parameterIndex, value);\n    } catch (IOException e) {\n      throw new SQLException(\"Error reading character stream\", e);\n    }\n  }\n\n  @Override\n  public void setRef(int parameterIndex, Ref x) throws SQLException {\n    // TODO\n  }\n\n  @Override\n  public void setBlob(int parameterIndex, Blob x) throws SQLException {\n    // TODO\n  }\n\n  @Override\n  public void setClob(int parameterIndex, Clob x) throws SQLException {\n    // TODO\n  }\n","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java#L406-L442","documentation":"setCharacterStream(int, Reader, int) copies up to length chars from the Reader into a String; any IOException from reader.read during the copy is wrapped in this SQLException. The SQL never runs — the failure is in the caller's Reader (closed, truncated, or broken source).","triggerScenarios":"Passing a closed FileReader/StringReader; the underlying file deleted or rotated mid-copy; a network-backed Reader resetting; a parser-backed Reader throwing on malformed input.","commonSituations":"File rotation racing the bind; Readers over sockets or remote storage; a Reader already drained by earlier code (that yields a short silent bind, not an error, unless the source itself throws).","solutions":["Unwrap SQLException.getCause() to find the real IOException and fix the source Reader's lifecycle.","Open the Reader and bind it in one try-with-resources scope.","Buffer the content first (read to String) and call setString for unreliable sources."],"exampleFix":"// before\nps.setCharacterStream(1, reader, len); // reader closed elsewhere\n\n// after\ntry (Reader r = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {\n    ps.setCharacterStream(1, r, Files.size(path));\n}","handlingStrategy":"try-catch","validationCode":"// fail fast if the reader is already closed\ntry {\n    reader.read();\n    // note: this consumes a char — prefer marking, or just rely on the catch below\n} catch (IOException closed) {\n    throw new IllegalStateException(\"reader closed before binding\", closed);\n}","typeGuard":null,"tryCatchPattern":"try {\n    ps.setCharacterStream(1, reader, len);\n} catch (SQLException e) {\n    if (e.getCause() instanceof IOException ioe) {\n        // Reader failure — reopen the source or fail with context\n    }\n    throw e;\n}","preventionTips":["Open Readers in try-with-resources at the bind site.","Do not share Readers across operations.","Buffer unstable sources to a String and bind with setString."],"tags":["jdbc","io","stream","parameter-binding"],"backgroundTag":"io-stream-read-failure","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}