BadRequestException thrown while querying the same non existing row twice. #106

Closed
dcapwell opened this Issue Aug 17, 2012 · 1 comment

Projects

None yet

2 participants

@dcapwell

If you query a row that doesn't exist, the first time query.execute will return an empty result. If you query it again with the same client, you will get a BadRequestException.

Here is sample code to reproduce this issue. set i < 1 will cause the query to be empty, i < 2 will cause the first request to be empty and the second to throw the exception:

UUID row = TimeUUIDUtils.getUniqueTimeUUIDinMicros();
ColumnFamily<UUID, String> CF = new ColumnFamily<UUID, String>("CF", TimeUUIDSerializer.get(), StringSerializer.get());

    for(int i = 0; i < 2; i++) {
      RowQuery<UUID, ContactColumn> query = keyspace.prepareQuery(CF)
          .getKey(row)
          .autoPaginate(true);

      ColumnList<ContactColumn> columns;
      while ( ! (columns = query.execute().getResult()).isEmpty() ) {
        // never called
        Assert.fail("Should never have been called");
      }
      LOGGER.info("Iteration {}", i);
    }

Here is the exception thrown:

com.netflix.astyanax.connectionpool.exceptions.BadRequestException: BadRequestException: [host=localhost(127.0.0.1):9160, latency=2(2), attempts=1] InvalidRequestException(why:get_slice requires non-negative count)
at com.netflix.astyanax.thrift.ThriftConverter.ToConnectionPoolException(ThriftConverter.java:159) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.thrift.AbstractOperationImpl.execute(AbstractOperationImpl.java:60) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.thrift.ThriftColumnFamilyQueryImpl$1$2.execute(ThriftColumnFamilyQueryImpl.java:196) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.thrift.ThriftColumnFamilyQueryImpl$1$2.execute(ThriftColumnFamilyQueryImpl.java:188) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.thrift.ThriftSyncConnectionFactoryImpl$1.execute(ThriftSyncConnectionFactoryImpl.java:131) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.connectionpool.impl.AbstractExecuteWithFailoverImpl.tryOperation(AbstractExecuteWithFailoverImpl.java:52) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.connectionpool.impl.AbstractHostPartitionConnectionPool.executeWithFailover(AbstractHostPartitionConnectionPool.java:229) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.thrift.ThriftColumnFamilyQueryImpl$1.execute(ThriftColumnFamilyQueryImpl.java:186) ~[astyanax-1.0.6.jar:na]
[...]
at java.lang.Thread.run(Thread.java:680) [na:1.6.0_33]
Caused by: org.apache.cassandra.thrift.InvalidRequestException: null
at org.apache.cassandra.thrift.Cassandra$get_slice_result.read(Cassandra.java:7196) ~[cassandra-thrift-1.1.0.jar:1.1.0]
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:78) ~[libthrift-0.7.0.jar:0.7.0]
at org.apache.cassandra.thrift.Cassandra$Client.recv_get_slice(Cassandra.java:543) ~[cassandra-thrift-1.1.0.jar:1.1.0]
at org.apache.cassandra.thrift.Cassandra$Client.get_slice(Cassandra.java:527) ~[cassandra-thrift-1.1.0.jar:1.1.0]
at com.netflix.astyanax.thrift.ThriftColumnFamilyQueryImpl$1$2.internalExecute(ThriftColumnFamilyQueryImpl.java:201) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.thrift.ThriftColumnFamilyQueryImpl$1$2.internalExecute(ThriftColumnFamilyQueryImpl.java:188) ~[astyanax-1.0.6.jar:na]
at com.netflix.astyanax.thrift.AbstractOperationImpl.execute(AbstractOperationImpl.java:55) ~[astyanax-1.0.6.jar:na]
... 59 common frames omitted
@dcapwell

Found the issue:

// ThriftColumnFamilyQueryImpl.java # 213
                                    // If this is the first page then adjust the
                                    // count so we fetch one extra column
                                    // that will later be dropped
                                    if (firstPage) {
                                        firstPage = false;
                                        predicate.getSlice_range().setCount(predicate.getSlice_range().getCount() + 1);
                                    }

The slice predicate that is currently defined is from ThriftUtils.RANGE_ALL, which uses Integer.MAX_VALUE, so when the +1 is added it flips to a negative value.

@elandau elandau closed this Nov 15, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment