apache/cassandra · error · InvalidRequestException

Virtual keyspace ' ' is not user-modifiable

Error message

Virtual keyspace '%s' is not user-modifiable

What it means

This InvalidRequestException is thrown when a schema-altering statement targets a virtual keyspace (e.g. 'system_views', 'system_virtual_schema'). Virtual keyspaces are in-memory views over runtime state with no underlying SSTables, so DDL against them is meaningless and rejected in AlterSchemaStatement.execute.

Solutions

  1. Do not issue DDL against virtual keyspaces; they are read-only projections of node state
  2. If you need different runtime settings, configure the underlying real keyspace or node configuration instead
  3. Filter virtual keyspaces out of automation loops (skip keyspaceMetadata.isVirtual())

Example fix

// before
session.execute("ALTER TABLE system_views.current_sessions WITH crc_check_chance = 0");
// after
// virtual tables are read-only; remove DDL against system_views
Defensive patterns

Strategy: validation

Validate before calling

KeyspaceMetadata ks = Schema.instance.getKeyspaceMetadata(keyspaceName);
if (ks != null && ks.isVirtual())
    throw new IllegalArgumentException("Refusing DDL on virtual keyspace: " + keyspaceName);

Type guard

boolean isVirtualKeyspace(String ks) {
    KeyspaceMetadata m = Schema.instance.getKeyspaceMetadata(ks);
    return m != null && m.isVirtual();
}

Try / catch

try {
    session.execute(ddl);
} catch (InvalidRequestException e) {
    if (e.getMessage().startsWith("Virtual keyspace"))
        log.warn("Skipped read-only virtual keyspace DDL: {}", ddl);
    else throw e;
}

Prevention

When it happens

Trigger: Executing any AlterSchemaStatement subclass where Schema.instance.getKeyspaceMetadata(keyspaceName) returns non-null and KeyspaceMetadata.isVirtual() is true, e.g. 'ALTER KEYSPACE system_views WITH replication = ...'

Common situations: Monitoring/ops scripts attempting to configure or index virtual tables; accidental tab-completion into system_views when writing DDL; tooling that iterates all keyspaces and applies DDL to each.

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/8f521265bda31cb1. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/AlterSchemaStatement.java:178

    /**
     * Schema alteration might produce a client warning (e.g. a warning to run full repair when increading RF of a keyspace).
     * This method should be used to generate them instead of calling warn() in transformation code.
     *
     * Only called if the transformation resulted in a non-empty diff.
     */
    Set<String> clientWarnings(KeyspacesDiff diff)
    {
        return ImmutableSet.of();
    }

    public ResultMessage execute(QueryState state)
    {
        if (SchemaConstants.isLocalSystemKeyspace(keyspaceName))
            throw ire("System keyspace '%s' is not user-modifiable", keyspaceName);

        KeyspaceMetadata keyspace = Schema.instance.getKeyspaceMetadata(keyspaceName);
        if (null != keyspace && keyspace.isVirtual())
            throw ire("Virtual keyspace '%s' is not user-modifiable", keyspaceName);

        validateKeyspaceName(keyspaceName, AlterSchemaStatement::ire);

        setExecutionTimestamp(state.getTimestamp());
        // Perform a 'dry-run' attempt to apply the transformation locally before submitting to the CMS. This can save a
        // round trip to the CMS for things syntax errors, but also fail fast for things like configuration errors.
        // Such failures may be dependent on the specific node's config (for things like guardrails/memtable
        // config/etc), but executing a schema change which has already been committed by the CMS should always succeed
        // or else the node cannot make progress on any subsequent metadata changes. For this reason, validation errors
        // during execution are trapped and the node will fall back to safe default config wherever possible. Attempting
        // to apply the SchemaTransformation at this point will catch any such error which occurs locally before
        // submission to the CMS, but it can't guarantee that the statement can be applied as-is on every node in the
        // cluster, as config can be heterogenous falling back to safe defaults may occur on some nodes.
        ClusterMetadata metadata = ClusterMetadata.current();
        Keyspaces proposed = apply(metadata);
        KeyspacesDiff localDiff =  Keyspaces.diff(metadata.schema.getKeyspaces(), proposed);
        if (localDiff.isEmpty())
            return new ResultMessage.Void();

View on GitHub (pinned to 88fd0f6a0e)