{"record":{"id":"ba845743d5454c7b","repo":"tursodatabase/turso","slug":"setasciistream-length-must-be-non-negative","errorCode":null,"errorMessage":"setAsciiStream length must be non-negative","messagePattern":"setAsciiStream length must be non-negative","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java","lineNumber":180,"sourceCode":"  public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {\n    requireNonNull(this.statement);\n    if (x == null) {\n      setParam(parameterIndex, null);\n    } else {\n      long time = x.getTime();\n      setParam(parameterIndex, ByteBuffer.allocate(Long.BYTES).putLong(time).array());\n    }\n  }\n\n  @Override\n  public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {\n    requireNonNull(this.statement);\n    if (x == null) {\n      setParam(parameterIndex, null);\n      return;\n    }\n    if (length < 0) {\n      throw new SQLException(\"setAsciiStream length must be non-negative\");\n    }\n    if (length == 0) {\n      setParam(parameterIndex, \"\");\n      return;\n    }\n    try {\n      byte[] buffer = new byte[length];\n      int offset = 0;\n      int read;\n      while (offset < length && (read = x.read(buffer, offset, length - offset)) > 0) {\n        offset += read;\n      }\n      String ascii = new String(buffer, 0, offset, StandardCharsets.US_ASCII);\n      setParam(parameterIndex, ascii);\n    } catch (IOException e) {\n      throw new SQLException(\"Error reading ASCII stream\", e);\n    }\n  }","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java#L162-L198","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nps.setAsciiStream(1, in, -1); // -1 sentinel not accepted -> SQLException\n\n// after\nps.setAsciiStream(1, in); // reads to EOF, no length needed","handlingStrategy":"validation","validationCode":"if (length < 0) {\n    ps.setAsciiStream(parameterIndex, stream); // unknown length: read to EOF\n} else {\n    ps.setAsciiStream(parameterIndex, stream, length);\n}","typeGuard":null,"tryCatchPattern":"try {\n    ps.setAsciiStream(i, in, length);\n} catch (SQLException e) {\n    if (e.getMessage().contains(\"non-negative\")) { ps.setAsciiStream(i, in); } else { throw e; }\n}","preventionTips":["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."],"tags":["java","jdbc","turso","parameter-binding","stream","input-validation"],"backgroundTag":"negative-stream-length","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}