tursodatabase/turso · error · SQLException
setBinaryStream length must be non-negative
Error message
setBinaryStream length must be non-negative
What it means
Thrown by setBinaryStream(int, InputStream, int) when length is negative. The driver validates the length before entering its 8 KiB chunked copy loop: a null stream binds SQL NULL and a zero length binds an empty byte array; only negative lengths are rejected at bind time.
Source
Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java:236
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);
}
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
requireNonNull(this.statement);
if (x == null) {
setParam(parameterIndex, null);
return;
}
if (length < 0) {
throw new SQLException("setBinaryStream length must be non-negative");
}
if (length == 0) {
setParam(parameterIndex, new byte[0]);
return;
}
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[8192];
int bytesRead;
int totalRead = 0;
while (totalRead < length
&& (bytesRead = x.read(buffer, 0, Math.min(buffer.length, length - totalRead))) > 0) {
baos.write(buffer, 0, bytesRead);
totalRead += bytesRead;
}
byte[] data = baos.toByteArray();
setParam(parameterIndex, data);
} catch (IOException e) {
throw new SQLException("Error reading binary stream", e);View on GitHub (pinned to bad083fafb)
Solutions
- Pass a non-negative byte count to setBinaryStream(int, InputStream, int).
- Use the no-length overload setBinaryStream(int, InputStream) when the size is unknown — it drains the stream to EOF.
- To bind NULL, pass a null stream or call setNull(i, Types.BLOB).
Example fix
// before long size = sizeOf(file); // returns -1 on error ps.setBinaryStream(1, in, (int) size); // after ps.setBinaryStream(1, in); // reads until EOF, no length needed
Defensive patterns
Strategy: validation
Validate before calling
if (length < 0) {
throw new IllegalArgumentException("length must be >= 0, got " + length);
}
ps.setBinaryStream(1, in, length); Try / catch
catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("non-negative")) {
// fix the length argument or switch to the no-length overload
}
throw e;
} Prevention
- Map error-code -1 from size lookups to a real exception instead of forwarding it as length.
- Use setBinaryStream(int, InputStream) when the size is unknown.
- Assert length >= 0 in a shared bind helper.
When it happens
Trigger: ps.setBinaryStream(i, in, -1); a file-size lookup that returned -1 (common error-code convention) forwarded directly as length; unsigned sizes widened into a negative int.
Common situations: Size probes (File.length() on a missing file returns 0, but custom lookups often return -1); code ported from drivers accepting -1 as 'unspecified'; length arithmetic that underflows.
Related errors
- setAsciiStream 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/ec4c7e9750944ff4.
Report an issue: GitHub.