apache/cassandra · warning · RuntimeException

Cache schema version + expected + does not match current sch

Error message

Cache schema version + expected + does not match current schema version + actual

What it means

AutoSavingCache.loadSaved reads a saved key/key-cache file whose header records the schema version UUID at the time the cache was persisted. On startup, the loader compares that UUID against ClusterMetadata.current().schema.getVersion(); if they differ, it throws this RuntimeException. The check exists because cache entries reference column families by name, which is ambiguous across schema versions — a stale cache could silently map keys to the wrong table.

Source

Thrown at src/java/org/apache/cassandra/cache/AutoSavingCache.java:227

        File metadataPath = getCacheMetadataPath(CURRENT_VERSION);
        if (dataPath.exists() && crcPath.exists() && metadataPath.exists())
        {
            DataInputStreamPlus in = null;
            try
            {
                logger.info("Reading saved cache: {}, {}, {}", dataPath, crcPath, metadataPath);
                try (FileInputStreamPlus metadataIn = metadataPath.newInputStream())
                {
                    cacheLoader.deserializeMetadata(metadataIn);
                }

                in = streamFactory.getInputStream(dataPath, crcPath);

                //Check the schema has not changed since CFs are looked up by name which is ambiguous
                UUID expected = new UUID(in.readLong(), in.readLong());
                UUID actual = ClusterMetadata.current().schema.getVersion();
                if (!expected.equals(actual))
                    throw new RuntimeException("Cache schema version "
                                               + expected
                                               + " does not match current schema version "
                                               + actual);

                ArrayDeque<Future<Pair<K, V>>> futures = new ArrayDeque<>();
                long loadByNanos = start + TimeUnit.SECONDS.toNanos(DatabaseDescriptor.getCacheLoadTimeout());
                while (nanoTime() < loadByNanos && in.available() > 0)
                {
                    Future<Pair<K, V>> entryFuture = cacheLoader.deserialize(in);
                    // Key cache entry can return null, if the SSTable doesn't exist.
                    if (entryFuture == null)
                        continue;

                    futures.offer(entryFuture);
                    count++;

                    /*
                     * Kind of unwise to accrue an unbounded number of pending futures

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. This is normally harmless and self-healing: acknowledge the RuntimeException in the log, and note Cassandra simply skips loading the stale cache (fresh entries rebuild on demand).
  2. If it recurs or blocks startup, stop the node and delete the stale files in the saved_caches directory (e.g. Keyspace-Table-KeyCache-*), then restart.
  3. Avoid restoring cache files from backups taken under a different schema; restore data and let caches rebuild.
  4. Perform schema migrations before/with restarts so cache snapshots and schema stay in sync where possible.

Example fix

// no code fix; remediation is clearing the stale cache on disk:
// before: saved_caches/Keyspace1-Standard1-KeyCache-<old-schema-uuid>.db loaded at startup -> RuntimeException
// after:  rm saved_caches/*KeyCache*  (or let Cassandra discard it), restart, cache rebuilds
Defensive patterns

Strategy: validation

Validate before calling

UUID current = ClusterMetadata.current().schema.getVersion();
java.io.File cacheFile = new java.io.File(DatabaseDescriptor.getSavedCachesLocation(), keyspace + "-" + table + "-KeyCache-");
// if saved cache files predate the latest schema change (e.g. timestamp < last DDL time), skip loading and let the cache rebuild

Try / catch

try { cache.loadSavedAsync(); }
catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().contains("does not match current schema version")) logger.warn("Skipping stale cache load; schema changed since cache was saved; rebuilding"); else throw e; }

Prevention

When it happens

Trigger: A node restarts with auto-saved cache files in the saved_caches directory that were written under a previous schema (any DDL change — CREATE/ALTER/DROP TABLE — made since the cache was saved, or cache files left over from a rollback/restore). loadSaved reads the header UUID and it no longer equals the current schema version.

Common situations: Operator changes schema (adds a table or column) and immediately restarts while caches_keys/saved_caches still hold pre-change files; restoring a node from a backup taken with an older schema; failed upgrade/rollback leaves stale cache files on disk.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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