apache/cassandra · warning

Maps differ: !=

Error message

Maps differ: {} != {}

What it means

Warning from DataPlacements.dumpDiff, a diagnostic helper that runs when two DataPlacements objects (replication placement per keyspace replication params) are not equal. It logs the full maps that differ and then delegates to a per-entry diff. Like the Directory dumpDiff warnings, it is logging-only, used to explain why a placement verification (e.g. during CMS initialization) failed.

Solutions

  1. Read the logged map diff to see which replication params/placements differ, then let CMS replicate the latest placement transforms so both nodes converge
  2. Check for interrupted ALTER TABLE / replication-factor changes and re-run them so placements are recalculated consistently
  3. Ensure both nodes run the same version before the migration so placement computation is identical
Defensive patterns

Strategy: validation

Validate before calling

if (!expectedPlacements.equals(ClusterMetadata.current().placements)) {
    expectedPlacements.dumpDiff(ClusterMetadata.current().placements);
    // resync placements before continuing
}

Prevention

When it happens

Trigger: DataPlacements.dumpDiff(other) is called after map.equals(other.map) fails — typically from a CMS initialization/migration verification path when the initiator's data placements differ from the local node's.

Common situations: A keyspace's replication settings (e.g. NetworkTopologyStrategy RF) were changed on some nodes but placement calculations diverged; pending replication changes were applied on the initiator but not the peer; nodes at different Cassandra versions computing placements differently.

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/88d7c9eef0fbb4c3. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/ownership/DataPlacements.java:306

                size += DataPlacement.serializerFor(entry.getKey()).serializedSize(entry.getValue(), version);
            }
            size += Epoch.serializer.serializedSize(t.lastModified, version);
            return size;
        }
    }

    public static ImmutableMap<ReplicationParams, DataPlacement> capLastModified(Epoch lastModified, Map<ReplicationParams, DataPlacement> placements)
    {
        ImmutableMap.Builder<ReplicationParams, DataPlacement> builder = ImmutableMap.builder();
        placements.forEach((params, placement) -> builder.put(params, placement.withCappedLastModified(lastModified)));
        return builder.build();
    }

    public void dumpDiff(DataPlacements other)
    {
        if (!map.equals(other.map))
        {
            logger.warn("Maps differ: {} != {}", map, other.map);
            dumpDiff(logger,map, other.map);
        }
    }

    private static final Logger logger = LoggerFactory.getLogger(DataPlacements.class);
    public static void dumpDiff(Logger logger, Map<ReplicationParams, DataPlacement> l, Map<ReplicationParams, DataPlacement> r)
    {
        for (ReplicationParams k : Sets.intersection(l.keySet(), r.keySet()))
        {
            DataPlacement lv = l.get(k);
            DataPlacement rv = r.get(k);
            if (!Objects.equals(lv, rv))
            {
                logger.warn("Values for key {} differ: {} != {}", k, lv, rv);
                logger.warn("Difference: {}", lv.difference(ClusterMetadata.current().directory, rv));
            }
        }
        for (ReplicationParams k : Sets.difference(l.keySet(), r.keySet()))

View on GitHub (pinned to 88fd0f6a0e)