apache/cassandra · error · RuntimeException

Snapshot for . already exists.

Error message

Snapshot %s for %s.%s already exists.

What it means

prePopulateSnapshots detects that a non-ephemeral snapshot with the same computed identity (tag + keyspace + table, matching manifest) already exists and refuses to create a duplicate. Ephemeral snapshots that collide are silently dropped instead.

Solutions

  1. Use a different snapshot tag, or include a timestamp component so each run resolves to a unique name.
  2. Clear the existing snapshot first (nodetool clearsnapshot -t <tag>) then retake it.
  3. Treat the error as 'snapshot already taken' and skip the operation if idempotency is desired.
  4. If ephemeral behavior is appropriate, mark the snapshot as ephemeral so the collision is dropped rather than thrown.

Example fix

// before
nodetool snapshot -t daily-backup ks1
// after (unique per run)
nodetool snapshot -t daily-backup-$(date +%Y%m%d%H%M%S) ks1
Defensive patterns

Strategy: validation

Validate before calling

boolean isUniqueTag(SnapshotManager mgr, String ks, String tbl, String tag) { return mgr.getSnapshots(ks, tbl).stream().noneMatch(s -> s.getTag().equals(tag)); }

Try / catch

try { takeSnapshot(tag, ks, tbl); } catch (RuntimeException e) { if (e.getMessage().contains("already exists")) { /* treat as success */ } else throw e; }

Prevention

When it happens

Trigger: Calling takeSnapshot with a tag that resolves to the same snapshot name for a table that already has that snapshot; re-running an idempotent script with the same explicit tag; named snapshot taken twice before clearing.

Common situations: Backup scripts with fixed tag names (e.g. 'daily') run twice; operators re-issue the same nodetool snapshot command; timestamp-generated names colliding within the same second.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/service/snapshot/SnapshotManager.java:587

     *
     * @param task task to process
     */
    private synchronized void prePopulateSnapshots(TakeSnapshotTask task)
    {
        Map<ColumnFamilyStore, TableSnapshot> snapshotsToCreate = task.getSnapshotsToCreate();
        Map<ColumnFamilyStore, TableSnapshot> snapshotsToOverwrite = new HashMap<>();
        List<TableSnapshot> toCreate = new ArrayList<>(snapshotsToCreate.values());

        for (TableSnapshot existingSnapshot : snapshots)
        {
            for (Map.Entry<ColumnFamilyStore, TableSnapshot> toCreateEntry : snapshotsToCreate.entrySet())
            {
                TableSnapshot snapshotToCreate = toCreateEntry.getValue();
                if (existingSnapshot.equals(toCreateEntry.getValue()))
                {
                    if (!task.options.ephemeral)
                    {
                        throw new RuntimeException(format("Snapshot %s for %s.%s already exists.",
                                                          snapshotToCreate.getTag(),
                                                          snapshotToCreate.getKeyspaceName(),
                                                          snapshotToCreate.getTableName()));
                    }

                    toCreate.remove(toCreateEntry.getValue());
                    snapshotsToOverwrite.put(toCreateEntry.getKey(), existingSnapshot);
                }
            }
        }

        snapshotsToCreate.putAll(snapshotsToOverwrite);

        snapshots.addAll(toCreate);
    }

    private static ScheduledExecutorPlus createSnapshotCleanupExecutor()
    {

View on GitHub (pinned to 88fd0f6a0e)