tursodatabase/turso · error · SQLException
Error reading ASCII stream
Error message
Error reading ASCII stream
What it means
setAsciiStream(int, InputStream, int) copies up to length bytes from the stream, decoding them as US-ASCII; any IOException raised by x.read during that copy is wrapped in this SQLException. The failure comes from the stream itself (closed handle, truncated file, dropped connection), not from SQL execution — the statement has not run yet when this is thrown.
Source
Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java:196
}
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);
}
}
@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 {View on GitHub (pinned to bad083fafb)
Solutions
- Unwrap the cause: SQLException.getCause() holds the original IOException — fix whatever it reports (keep the source alive until the bind completes).
- Open the stream and bind it inside the same try-with-resources block so nothing closes it early.
- For remote or unstable sources, download to a byte[] or temp file first, then bind with setBytes or a ByteArrayInputStream.
Example fix
// before
InputStream in = Files.newInputStream(path);
// ...later: file deleted, read fails
ps.setAsciiStream(1, in, (int) size);
// after
try (InputStream in = Files.newInputStream(path)) {
ps.setAsciiStream(1, in, (int) Files.size(path));
} Defensive patterns
Strategy: try-catch
Validate before calling
// fail fast if the stream is already closed
try {
in.available();
} catch (IOException closed) {
throw new IllegalStateException("stream closed before binding", closed);
} Try / catch
try {
ps.setAsciiStream(1, in, len);
} catch (SQLException e) {
if (e.getCause() instanceof IOException ioe) {
// source-stream failure: reopen the source and retry once, or report context
throw new DataAccessException("ASCII stream unreadable", ioe);
}
throw e;
} Prevention
- Open streams in try-with-resources at the binding site, not far away.
- Do not delete, rotate, or close stream sources before the bind completes.
- Add timeouts/retries around remote streams, or buffer them locally first.
When it happens
Trigger: Passing an already-closed InputStream; the backing file is deleted or rotated between open and bind; a network or GZIP stream raises IOException mid-copy; another component consumed or invalidated the stream first.
Common situations: Log rotation deleting a file after FileInputStream creation; streaming from HTTP/S3 where the connection resets; streams closed by an outer try-with-resources before the bind call.
Related errors
- Error reading Unicode stream
- Error reading binary stream
- Error reading character 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/49a4cf12cfc84133.
Report an issue: GitHub.