tursodatabase/turso · error · SQLException
setAsciiStream length must be non-negative
Error message
setAsciiStream length must be non-negative
What it means
Thrown by setAsciiStream(int, InputStream, int) when the caller passes a negative length. The JDBC contract requires length to be a non-negative byte count, and this driver validates it up front, before allocating the read buffer, so a bad length is rejected at bind time without reading the stream. Note the neighboring cases: 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:180
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
requireNonNull(this.statement);
if (x == null) {
setParam(parameterIndex, null);
} else {
long time = x.getTime();
setParam(parameterIndex, ByteBuffer.allocate(Long.BYTES).putLong(time).array());
}
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
requireNonNull(this.statement);
if (x == null) {
setParam(parameterIndex, null);
return;
}
if (length < 0) {
throw new SQLException("setAsciiStream 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 ascii = new String(buffer, 0, offset, StandardCharsets.US_ASCII);
setParam(parameterIndex, ascii);
} catch (IOException e) {
throw new SQLException("Error reading ASCII stream", e);
}
}View on GitHub (pinned to bad083fafb)
Solutions
- Pass an exact non-negative byte count to setAsciiStream(int, InputStream, int).
- If the length is unknown, call the no-length overload setAsciiStream(int, InputStream), which reads the stream until EOF.
- To bind SQL NULL, pass a null stream (already handled by the driver) or use setNull(i, Types.VARCHAR) instead of a length trick.
Example fix
// before ps.setAsciiStream(1, in, -1); // throws: length must be non-negative // after ps.setAsciiStream(1, in); // reads the stream until EOF
Defensive patterns
Strategy: validation
Validate before calling
if (length < 0) {
throw new IllegalArgumentException("length must be >= 0, got " + length);
}
ps.setAsciiStream(1, in, length); Try / catch
catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("non-negative")) {
// programmer error in the length argument — fix the caller, do not retry
}
throw e;
} Prevention
- Never use -1 or Long.MAX_VALUE as an 'unknown length' sentinel with this driver; use the two-argument setAsciiStream(int, InputStream) overload.
- Validate lengths coming from config or external APIs before binding.
- Centralize stream binding in one helper that asserts length >= 0.
When it happens
Trigger: Calling ps.setAsciiStream(i, in, -1); forwarding a computed length that underflowed or defaulted to -1; porting code that uses the InputStream.read() convention where -1 means 'read to EOF'.
Common situations: Reusable DAO layers that accept an optional length and forward -1 when the size is unknown; lengths from unsigned sources stored into a signed int; code copied from drivers where -1 meant 'unspecified'.
Related errors
- setBinaryStream length must be non-negative
- setCharacterStream length must be non-negative
- Error reading ASCII stream
- setUnicodeStream length must be non-negative
- Error reading Unicode stream
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/ba845743d5454c7b.
Report an issue: GitHub.