apache/cassandra · warning

Loading cluster metadata from

Error message

Loading cluster metadata from {}

What it means

ClusterMetadataService.loadClusterMetadata logs a warning while importing cluster metadata from a previously dumped file. It deserializes the snapshot, forces a new epoch ahead of the current one, and commits it as a forced snapshot — effectively replacing the cluster's metadata with the file's contents.

Solutions

  1. Ensure the dump file is from the same cluster and era; loading foreign metadata can corrupt topology.
  2. Take a current `nodetool cms dump` before loading for rollback safety.
  3. Confirm all nodes are up and reachable so the forced snapshot commits with quorum.
  4. If the file is unreadable or wrong, re-dump from a healthy node and retry.
Defensive patterns

Strategy: try-catch

Validate before calling

// validate dump file exists and deserializes before applying
ClusterMetadata m = deserializeClusterMetadata(file); // throws IOException if bad
if (m == null) throw new IOException("empty or invalid metadata dump");

Try / catch

try { loadClusterMetadata(file); } catch (IOException e) { logger.error("metadata load failed; dump file may be corrupt", e); }

Prevention

When it happens

Trigger: An operator calls loadClusterMetadata(file) (exposed via nodetool cms load) to restore metadata from a `cms dump` file.

Common situations: Disaster recovery after the TCM log/snapshot was lost or corrupted; recreating a cluster's metadata; migrating metadata between clusters.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/ClusterMetadataService.java:593

     */
    public String dumpClusterMetadata(Epoch epoch, Epoch transformToEpoch, Version version) throws IOException
    {
        ClusterMetadata toDump = epoch.isAfter(Epoch.EMPTY)
                                 ? transformSnapshot(LogState.getForRecovery(epoch))
                                 : ClusterMetadata.current();
        toDump = toDump.forceEpoch(transformToEpoch);
        Path p = Files.createTempFile("clustermetadata", "dump");
        try (FileOutputStreamPlus out = new FileOutputStreamPlus(p))
        {
            VerboseMetadataSerializer.serialize(ClusterMetadata.serializer, toDump, out, version);
        }
        logger.info("Dumped cluster metadata to {}", p.toString());
        return p.toString();
    }

    public void loadClusterMetadata(String file) throws IOException
    {
        logger.warn("Loading cluster metadata from {}", file);
        ClusterMetadata metadata = ClusterMetadata.current();
        ClusterMetadata toApply = deserializeClusterMetadata(file)
                                  .forceEpoch(metadata.epoch.nextEpoch());
        forceSnapshot(toApply);
    }

    public static ClusterMetadata deserializeClusterMetadata(String file) throws IOException
    {
        try (FileInputStreamPlus fisp = new FileInputStreamPlus(file))
        {
            return VerboseMetadataSerializer.deserialize(ClusterMetadata.serializer, fisp);
        }
    }

    private ClusterMetadata transformSnapshot(LogState state)
    {
        ClusterMetadata toApply = state.baseState;
        for (Entry entry : state.entries)

View on GitHub (pinned to 88fd0f6a0e)