tursodatabase/turso · error · SQLException
Error reading character stream
Error message
Error reading character stream
What it means
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).
Source
Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java:424
}
if (length < 0) {
throw new SQLException("setCharacterStream length must be non-negative");
}
if (length == 0) {
setParam(parameterIndex, "");
return;
}
try {
char[] buffer = new char[length];
int offset = 0;
int read;
while (offset < length && (read = reader.read(buffer, offset, length - offset)) > 0) {
offset += read;
}
String value = new String(buffer, 0, offset);
setParam(parameterIndex, value);
} catch (IOException e) {
throw new SQLException("Error reading character stream", e);
}
}
@Override
public void setRef(int parameterIndex, Ref x) throws SQLException {
// TODO
}
@Override
public void setBlob(int parameterIndex, Blob x) throws SQLException {
// TODO
}
@Override
public void setClob(int parameterIndex, Clob x) throws SQLException {
// TODO
}
View on GitHub (pinned to bad083fafb)
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.
Example fix
// before
ps.setCharacterStream(1, reader, len); // reader closed elsewhere
// after
try (Reader r = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
ps.setCharacterStream(1, r, Files.size(path));
} Defensive patterns
Strategy: try-catch
Validate before calling
// fail fast if the reader is already closed
try {
reader.read();
// note: this consumes a char — prefer marking, or just rely on the catch below
} catch (IOException closed) {
throw new IllegalStateException("reader closed before binding", closed);
} Try / catch
try {
ps.setCharacterStream(1, reader, len);
} catch (SQLException e) {
if (e.getCause() instanceof IOException ioe) {
// Reader failure — reopen the source or fail with context
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Error reading ASCII stream
- Error reading Unicode stream
- Error reading binary stream
- Error reading InputStream
- setAsciiStream length must be non-negative
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/f9f7f9e80b74595a.
Report an issue: GitHub.