tursodatabase/turso · error · SQLException
setUnicodeStream length must be non-negative
Error message
setUnicodeStream length must be non-negative
What it means
Thrown by setUnicodeStream(int, InputStream, int) when length is negative. setUnicodeStream is the deprecated JDBC 1 stream API; this driver still implements it (copying length bytes and decoding as UTF-8) but enforces a non-negative length exactly like setAsciiStream. A null stream binds SQL NULL and a zero length binds an empty string; only negative lengths throw.
Source
Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java:208
while (offset < length && (read = x.read(buffer, offset, length - offset)) > 0) {
offset += read;
}
String ascii = new String(buffer, 0, offset, StandardCharsets.US_ASCII);
setParam(parameterIndex, ascii);
} catch (IOException e) {
throw new SQLException("Error reading ASCII stream", e);
}
}
@Override
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
requireNonNull(this.statement);
if (x == null) {
setParam(parameterIndex, null);
return;
}
if (length < 0) {
throw new SQLException("setUnicodeStream length must be non-negative");
}
if (length == 0) {
setParam(parameterIndex, "");
return;
}
try {
byte[] buffer = new byte[length];
int offset = 0;
int read;
while (offset < length && (read = x.read(buffer, offset, length - offset)) > 0) {
offset += read;
}
String text = new String(buffer, 0, offset, StandardCharsets.UTF_8);
setParam(parameterIndex, text);
} catch (IOException e) {
throw new SQLException("Error reading Unicode stream", e);
}
}View on GitHub (pinned to bad083fafb)
Solutions
- Pass a non-negative byte count.
- Replace setUnicodeStream with setCharacterStream(i, reader, length) — the supported replacement with identical semantics for UTF-8 text.
- For unknown length use the no-length setCharacterStream(i, reader) overload rather than a sentinel.
Example fix
// before ps.setUnicodeStream(1, in, -1); // after ps.setCharacterStream(1, new InputStreamReader(in, StandardCharsets.UTF_8));
Defensive patterns
Strategy: validation
Validate before calling
if (length < 0) {
throw new IllegalArgumentException("length must be >= 0, got " + length);
}
ps.setCharacterStream(1, new InputStreamReader(in, StandardCharsets.UTF_8), length); Try / catch
catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("non-negative")) {
// fix the length argument; consider migrating to setCharacterStream
}
throw e;
} Prevention
- Prefer setCharacterStream over the deprecated setUnicodeStream everywhere.
- Treat -1 as an invalid length, never as 'read to EOF'.
- Keep one shared stream-binding helper with length validation.
When it happens
Trigger: ps.setUnicodeStream(i, in, -1) or a negative computed length; legacy code paths that still call the deprecated method and use -1 as an 'unknown length' sentinel.
Common situations: Old JDBC 1-era codebases kept alive; lengths read from external config that default to -1; maintainers surprised that the deprecated method still validates its arguments.
Related errors
- setAsciiStream length must be non-negative
- Error reading Unicode stream
- setBinaryStream length must be non-negative
- setCharacterStream length must be non-negative
- Error reading ASCII stream
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/f21c3394310bc09a.
Report an issue: GitHub.