apache/cassandra · error · IllegalArgumentException

Cannot instantiate a non-virtual table

Error message

Cannot instantiate a non-virtual table

What it means

AbstractVirtualTable's constructor validates that the TableMetadata passed in is flagged virtual. Constructing a virtual-table instance for a regular (disk-backed) table metadata would break the contract that virtual tables are purely in-memory, so IllegalArgumentException is thrown at construction time. This is a developer-facing invariant check, not a runtime query error.

Source

Thrown at src/java/org/apache/cassandra/db/virtual/AbstractVirtualTable.java:55

import org.apache.cassandra.db.partitions.UnfilteredPartitionIterator;
import org.apache.cassandra.db.rows.UnfilteredRowIterator;
import org.apache.cassandra.dht.AbstractBounds;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.schema.TableMetadata;

import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;

/**
 * An abstract virtual table implementation that builds the resultset on demand.
 */
public abstract class AbstractVirtualTable implements VirtualTable
{
    protected final TableMetadata metadata;

    protected AbstractVirtualTable(TableMetadata metadata)
    {
        if (!metadata.isVirtual())
            throw new IllegalArgumentException("Cannot instantiate a non-virtual table");

        this.metadata = metadata;
    }

    public TableMetadata metadata()
    {
        return metadata;
    }

    /**
     * Provide a {@link DataSet} that is contains all of the virtual table's data.
     */
    public abstract DataSet data();

    /**
     * Provide a {@link DataSet} that is potentially restricted to the provided partition - but is allowed to contain
     * other partitions.
     */

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Add .virtual() to the TableMetadata builder before constructing the table
  2. Verify the table is registered in a VirtualKeyspace, not a regular Schema keyspace
  3. Double-check the factory (AbstractVirtualTable.Factory) receives metadata created for the virtual schema

Example fix

// before
TableMetadata metadata = TableMetadata.builder("my_vks", "my_table")
    .addPartitionKeyColumn("k", UTF8Type.instance)
    .build(); // not virtual
// after
TableMetadata metadata = TableMetadata.builder("my_vks", "my_table")
    .virtual()
    .addPartitionKeyColumn("k", UTF8Type.instance)
    .build();
Defensive patterns

Strategy: validation

Validate before calling

if (!metadata.isVirtual()) throw new IllegalArgumentException("must pass virtual TableMetadata to virtual table constructor");

Type guard

boolean isVirtualMeta = m -> m.isVirtual();

Try / catch

try { new MyVirtualTable(metadata); } catch (IllegalArgumentException e) { rebuildMetadataAsVirtual(); }

Prevention

When it happens

Trigger: Registering a VirtualTable implementation with TableMetadata built without .virtual() (e.g. forgetting TableMetadata.builder(...).virtual() or adding the table to the wrong registry — VirtualKeyspace vs regular keyspace).

Common situations: Developing a custom virtual table and forgetting the .virtual() flag on the builder; wiring an existing table's metadata into VirtualTable.initialize; copy-paste of a regular table definition into a virtual keyspace.

Related errors


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