apache/cassandra · error · InvalidRequestException

Invalid null value for slice selection on

Error message

Invalid null value for slice selection on 

What it means

Slice selection (e.g. SELECT s[?..?]) treats UNSET values as 'no bound', so a NULL bound endpoint is genuinely invalid. When either the from or to term binds to null (an explicit null parameter rather than unset), newInstance throws this error before building the SliceSelector.

Solutions

  1. Pass UNSET / omit the variable instead of null for an open-ended bound
  2. Use literal bounds in the CQL text (e.g. col[..5]) when the bound is static
  3. Validate bound parameters for null before executing the statement

Example fix

// before
bs.setBytes(0, null); // intended as open lower bound
// after
bs.setToUnset(0); // or: SELECT col[..5] literally
Defensive patterns

Strategy: validation

Validate before calling

if (fromBound == null || toBound == null)
    throw new IllegalArgumentException("slice bounds must not be null; use UNSET for open bounds");

Prevention

When it happens

Trigger: SELECT setOrMap[?..?] where at least one of the bound endpoint variables is explicitly set to null in the query parameters.

Common situations: Application code passes Java null for a slice bound intending 'open-ended'; in Cassandra open-ended slices use UNSET (omit) or literal bounds, not null.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/a1dd7ac67957e9b1. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/selection/ElementsSelector.java:217

     * {@code Constants.UNSET_VALUE} if the slice doesn't have an end.
     * @return the created factory.
     */
    public static Factory newSliceFactory(String name, Selector.Factory factory, CollectionType<?> type, final Term from, final Term to)
    {
        return new AbstractFactory(name, factory, type)
        {
            protected AbstractType<?> getReturnType()
            {
                return type;
            }

            public Selector newInstance(QueryOptions options) throws InvalidRequestException
            {
                ByteBuffer fromValue = from.bindAndGet(options);
                ByteBuffer toValue = to.bindAndGet(options);
                // Note that we use UNSET values to represent no bound, so null is truly invalid
                if (fromValue == null || toValue == null)
                    throw new InvalidRequestException("Invalid null value for slice selection on " + factory.getColumnName());
                return new SliceSelector(factory.newInstance(options), from.bindAndGet(options), to.bindAndGet(options));
            }

            public boolean areAllFetchedColumnsKnown()
            {
                // If we known all the fetched columns, it means that we don't have to wait execution to create
                // the ColumnFilter (through addFetchedColumns below).
                // That's the case if either there is no particular subselection
                // to add, or if there is one but the selected bound are terminal. In other words,
                // we known all the fetched columns if all the feched columns of the factory are known and either:
                //  1) the type is frozen (in which case there isn't subselection to do).
                //  2) the factory (the left-hand-side) isn't a simple column selection (here again, no
                //     subselection we can do).
                //  3) the bound of the selected slice are terminal.
                return factory.areAllFetchedColumnsKnown()
                        && (!type.isMultiCell() || !factory.isSimpleSelectorFactory() || (from.isTerminal() && to.isTerminal()));
            }

View on GitHub (pinned to 88fd0f6a0e)