{"record":{"id":"ec4c7e9750944ff4","repo":"tursodatabase/turso","slug":"setbinarystream-length-must-be-non-negative","errorCode":null,"errorMessage":"setBinaryStream length must be non-negative","messagePattern":"setBinaryStream 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":236,"sourceCode":"      while (offset < length && (read = x.read(buffer, offset, length - offset)) > 0) {\n        offset += read;\n      }\n      String text = new String(buffer, 0, offset, StandardCharsets.UTF_8);\n      setParam(parameterIndex, text);\n    } catch (IOException e) {\n      throw new SQLException(\"Error reading Unicode stream\", e);\n    }\n  }\n\n  @Override\n  public void setBinaryStream(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(\"setBinaryStream length must be non-negative\");\n    }\n    if (length == 0) {\n      setParam(parameterIndex, new byte[0]);\n      return;\n    }\n    try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {\n      byte[] buffer = new byte[8192];\n      int bytesRead;\n      int totalRead = 0;\n      while (totalRead < length\n          && (bytesRead = x.read(buffer, 0, Math.min(buffer.length, length - totalRead))) > 0) {\n        baos.write(buffer, 0, bytesRead);\n        totalRead += bytesRead;\n      }\n      byte[] data = baos.toByteArray();\n      setParam(parameterIndex, data);\n    } catch (IOException e) {\n      throw new SQLException(\"Error reading binary stream\", e);","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java#L218-L254","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nlong size = sizeOf(file); // returns -1 on error\nps.setBinaryStream(1, in, (int) size);\n\n// after\nps.setBinaryStream(1, in); // reads until EOF, no length needed","handlingStrategy":"validation","validationCode":"if (length < 0) {\n    throw new IllegalArgumentException(\"length must be >= 0, got \" + length);\n}\nps.setBinaryStream(1, in, length);","typeGuard":null,"tryCatchPattern":"catch (SQLException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"non-negative\")) {\n        // fix the length argument or switch to the no-length overload\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["jdbc","parameter-binding","input-validation","stream"],"backgroundTag":"jdbc-invalid-parameter-value","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}