{"record":{"id":"3d2c03adece08f9a","repo":"apache/cassandra","slug":"cannot-instantiate-a-non-virtual-table","errorCode":null,"errorMessage":"Cannot instantiate a non-virtual table","messagePattern":"Cannot instantiate a non-virtual table","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/virtual/AbstractVirtualTable.java","lineNumber":55,"sourceCode":"import org.apache.cassandra.db.partitions.UnfilteredPartitionIterator;\nimport org.apache.cassandra.db.rows.UnfilteredRowIterator;\nimport org.apache.cassandra.dht.AbstractBounds;\nimport org.apache.cassandra.exceptions.InvalidRequestException;\nimport org.apache.cassandra.schema.TableMetadata;\n\nimport static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;\n\n/**\n * An abstract virtual table implementation that builds the resultset on demand.\n */\npublic abstract class AbstractVirtualTable implements VirtualTable\n{\n    protected final TableMetadata metadata;\n\n    protected AbstractVirtualTable(TableMetadata metadata)\n    {\n        if (!metadata.isVirtual())\n            throw new IllegalArgumentException(\"Cannot instantiate a non-virtual table\");\n\n        this.metadata = metadata;\n    }\n\n    public TableMetadata metadata()\n    {\n        return metadata;\n    }\n\n    /**\n     * Provide a {@link DataSet} that is contains all of the virtual table's data.\n     */\n    public abstract DataSet data();\n\n    /**\n     * Provide a {@link DataSet} that is potentially restricted to the provided partition - but is allowed to contain\n     * other partitions.\n     */","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/virtual/AbstractVirtualTable.java#L37-L73","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Add .virtual() to the TableMetadata builder before constructing the table","Verify the table is registered in a VirtualKeyspace, not a regular Schema keyspace","Double-check the factory (AbstractVirtualTable.Factory) receives metadata created for the virtual schema"],"exampleFix":"// before\nTableMetadata metadata = TableMetadata.builder(\"my_vks\", \"my_table\")\n    .addPartitionKeyColumn(\"k\", UTF8Type.instance)\n    .build(); // not virtual\n// after\nTableMetadata metadata = TableMetadata.builder(\"my_vks\", \"my_table\")\n    .virtual()\n    .addPartitionKeyColumn(\"k\", UTF8Type.instance)\n    .build();","handlingStrategy":"validation","validationCode":"if (!metadata.isVirtual()) throw new IllegalArgumentException(\"must pass virtual TableMetadata to virtual table constructor\");","typeGuard":"boolean isVirtualMeta = m -> m.isVirtual();","tryCatchPattern":"try { new MyVirtualTable(metadata); } catch (IllegalArgumentException e) { rebuildMetadataAsVirtual(); }","preventionTips":["Always call .virtual() on the TableMetadata builder for virtual tables","Register virtual tables only in VirtualKeyspace instances","Add a unit test constructing each virtual table at startup"],"tags":["virtual-table","schema","developer-error","illegal-argument"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}