{"record":{"id":"d7741a52cb5c11bb","repo":"tursodatabase/turso","slug":"setcharacterstream-length-must-be-non-negative","errorCode":null,"errorMessage":"setCharacterStream length must be non-negative","messagePattern":"setCharacterStream 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":408,"sourceCode":"    batchQueryParams.add(currentBatchParams);\n    currentBatchParams = new Object[paramCount];\n  }\n\n  @Override\n  public void addBatch(String sql) throws SQLException {\n    throw new SQLException(\"addBatch(String) cannot be called on a PreparedStatement\");\n  }\n\n  @Override\n  public void setCharacterStream(int parameterIndex, @Nullable Reader reader, int length)\n      throws SQLException {\n    requireNonNull(this.statement);\n    if (reader == null) {\n      setParam(parameterIndex, null);\n      return;\n    }\n    if (length < 0) {\n      throw new SQLException(\"setCharacterStream length must be non-negative\");\n    }\n    if (length == 0) {\n      setParam(parameterIndex, \"\");\n      return;\n    }\n    try {\n      char[] buffer = new char[length];\n      int offset = 0;\n      int read;\n      while (offset < length && (read = reader.read(buffer, offset, length - offset)) > 0) {\n        offset += read;\n      }\n      String value = new String(buffer, 0, offset);\n      setParam(parameterIndex, value);\n    } catch (IOException e) {\n      throw new SQLException(\"Error reading character stream\", e);\n    }\n  }","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java#L390-L426","documentation":"Thrown by setCharacterStream(int, Reader, int) when length is negative. The driver validates the length before copying length chars from the Reader into a String: a null Reader binds SQL NULL and a zero length binds an empty string; only negative lengths throw.","triggerScenarios":"ps.setCharacterStream(i, reader, -1); forwarding a computed char count that underflowed or defaulted to -1; using the InputStream.read() -1-equals-EOF convention where a length is expected.","commonSituations":"DAO layers that accept an optional length and pass -1 when unknown; counts from external systems stored in signed ints; sentinel conventions copied from other drivers.","solutions":["Pass a non-negative char count.","Use the no-length overload setCharacterStream(i, reader), which reads until EOF.","To bind NULL, use setNull(i, Types.VARCHAR) or pass a null Reader."],"exampleFix":"// before\nps.setCharacterStream(1, reader, -1); // throws\n\n// after\nps.setCharacterStream(1, reader); // reads until EOF","handlingStrategy":"validation","validationCode":"if (length < 0) {\n    throw new IllegalArgumentException(\"length must be >= 0, got \" + length);\n}\nps.setCharacterStream(1, reader, 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":["Use setCharacterStream(i, reader) when the char count is unknown.","Validate char counts from external sources before binding.","One shared helper, one length check."],"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"}