tursodatabase/turso · error · SQLException
setAsciiStream length must be non-negative
Error message
setAsciiStream length must be non-negative
What it means
JDBC4PreparedStatement.setAsciiStream(int, InputStream, int) validates its length argument before reading: a negative length is rejected with SQLException at JDBC4PreparedStatement.java:180. Some other drivers accept -1 as an 'unknown length, read to EOF' sentinel; this one does not. If you do not know the length up front, the two-argument overload setAsciiStream(int, InputStream) reads the whole stream.
Solutions
- If the length is unknown, use setAsciiStream(parameterIndex, stream) - it reads the stream to EOF.
- Compute the exact non-negative byte length before calling (e.g., file.length(), byte array length, buffered stream size).
- Validate and clamp: if (length < 0) length = (int) stream.available() or buffer fully and use setString.
- Fix the producer that supplies -1 so it reports the real size.
Example fix
// before ps.setAsciiStream(1, in, -1); // -1 sentinel not accepted -> SQLException // after ps.setAsciiStream(1, in); // reads to EOF, no length needed
Defensive patterns
Strategy: validation
Validate before calling
if (length < 0) {
ps.setAsciiStream(parameterIndex, stream); // unknown length: read to EOF
} else {
ps.setAsciiStream(parameterIndex, stream, length);
} Try / catch
try {
ps.setAsciiStream(i, in, length);
} catch (SQLException e) {
if (e.getMessage().contains("non-negative")) { ps.setAsciiStream(i, in); } else { throw e; }
} Prevention
- Never pass -1 length sentinels - this driver rejects them.
- Prefer the two-argument overload when size is unknown.
- Compute lengths from reliable sources (file size, array length).
- Validate caller-supplied lengths at wrapper boundaries.
When it happens
Trigger: Passing -1 as a length sentinel copied from MySQL/PostgreSQL-oriented code; computing length via an underflowing subtraction or a signed conversion; passing a length obtained from a source that returns -1 for 'unknown' (e.g., some file/net layers); null stream is fine (binds NULL) - only negative length throws.
Common situations: Generic JDBC wrapper libraries that forward caller-supplied lengths verbatim; streaming uploads where the size is not known in advance and -1 is the codebase convention; ports of older code using the deprecated 3-arg stream API; unit tests with placeholder -1 values.
Related errors
- setBinaryStream length must be non-negative
- setUnicodeStream length must be non-negative
- Error reading ASCII stream
- Error reading binary stream
- Error reading Unicode stream
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/ba845743d5454c7b.
Report an issue: GitHub.
Appendix: 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 244cde92a7)