tursodatabase/turso · error · SQLFeatureNotSupportedException

Data must have a length between 0 and Integer.MAX_VALUE

Error message

Data must have a length between 0 and Integer.MAX_VALUE

What it means

The long-length overloads — setAsciiStream(i, in, long), setBinaryStream(i, in, long), setCharacterStream(i, reader, long) — all funnel through requireLengthIsPositiveInt, which throws SQLFeatureNotSupportedException when length is negative or greater than Integer.MAX_VALUE. The driver will not buffer more than 2 GiB in a single bind and reports oversized lengths as an unsupported feature, not a plain validation error. Since SQLFeatureNotSupportedException extends SQLException, a normal SQLException catch covers it.

Source

Thrown at bindings/java/src/main/java/tech/turso/jdbc4/JDBC4PreparedStatement.java:555

    setAsciiStream(parameterIndex, x, (int) length);
  }

  @Override
  public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
    requireLengthIsPositiveInt(length);
    setBinaryStream(parameterIndex, x, (int) length);
  }

  @Override
  public void setCharacterStream(int parameterIndex, @Nullable Reader reader, long length)
      throws SQLException {
    requireLengthIsPositiveInt(length);
    setCharacterStream(parameterIndex, reader, (int) length);
  }

  private void requireLengthIsPositiveInt(long length) throws SQLFeatureNotSupportedException {
    if (length > Integer.MAX_VALUE || length < 0) {
      throw new SQLFeatureNotSupportedException(
          "Data must have a length between 0 and Integer.MAX_VALUE");
    }
  }

  @Override
  public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
    requireNonNull(this.statement);
    if (x == null) {
      setParam(parameterIndex, null);
      return;
    }
    byte[] data = readBytes(x);
    String ascii = new String(data, StandardCharsets.US_ASCII);
    setParam(parameterIndex, ascii);
  }

  @Override
  public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {

View on GitHub (pinned to bad083fafb)

Solutions

  1. For 'whole stream' semantics use the two-argument overloads: setAsciiStream(i, in), setBinaryStream(i, in), setCharacterStream(i, reader) — they read to EOF with no length argument.
  2. Split payloads larger than Integer.MAX_VALUE into chunks (multiple rows or ranges), since one bind cannot exceed 2 GiB in this driver.
  3. Clamp and validate external lengths to [0, Integer.MAX_VALUE] before calling any long-length overload.

Example fix

// before
ps.setCharacterStream(1, reader, Long.MAX_VALUE); // throws SQLFeatureNotSupportedException

// after
ps.setCharacterStream(1, reader); // reads until EOF
Defensive patterns

Strategy: validation

Validate before calling

static int toBindLength(long len) {
    if (len < 0 || len > Integer.MAX_VALUE) {
        throw new IllegalArgumentException("bind length out of int range: " + len);
    }
    return (int) len;
}
// or skip lengths entirely: setBinaryStream(i, in) / setCharacterStream(i, reader)

Try / catch

catch (SQLFeatureNotSupportedException e) {
    // driver cannot bind this size — split the payload or use the no-length overload
}

Prevention

When it happens

Trigger: ps.setCharacterStream(1, reader, Long.MAX_VALUE) used as an 'until EOF' sentinel; binding the exact size of a file larger than 2 GiB; a negative long length from an unsigned source widened into signed.

Common situations: Reusing the Long.MAX_VALUE / -1 'unbounded' convention from other drivers; large media or LOB pipelines; migrating from drivers that stream long lengths lazily.

Related errors


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/c131c5a6abe77fa8. Report an issue: GitHub.