apache/cassandra · error · IllegalStateException
can not take ephemeral snapshot
Error message
can not take ephemeral snapshot (%s) while ttl is specified too
What it means
validateTTL rejects combining an ephemeral snapshot with an explicit ttl, throwing IllegalStateException. Ephemeral snapshots are transient by definition (deleted as soon as their session ends), so attaching a TTL is contradictory. The two options are mutually exclusive at the builder level.
Solutions
- Remove the --ttl flag when taking an ephemeral snapshot.
- If TTL-based retention is needed, take a regular (non-ephemeral) snapshot with a ttl instead.
- Update wrapper scripts so ephemeral and ttl options are mutually exclusive.
Example fix
// before nodetool snapshot --ephemeral -t tmp --ttl 10m // after nodetool snapshot --ephemeral -t tmp
Defensive patterns
Strategy: validation
Validate before calling
if (ephemeral && ttl != null) throw new IllegalArgumentException("ephemeral snapshots cannot specify ttl"); Try / catch
try { takeSnapshot(opts); } catch (IllegalStateException e) { if (e.getMessage().contains("ephemeral")) takeSnapshot(opts.withoutTtl()); else throw e; } Prevention
- Treat ephemeral and ttl as mutually exclusive flags in tooling
- Document in wrapper scripts that ephemeral implies no ttl
- Add config-layer validation before calling the snapshot API
When it happens
Trigger: nodetool snapshot --ephemeral --ttl 10m, or SnapshotOptions.builder().ephemeral(true).withTTL(...) — any call where both ephemeral=true and ttl != null reach build().
Common situations: Tooling that always sets a default TTL but was switched to ephemeral snapshots; users combining flags assuming TTL governs cleanup of ephemeral snapshots; script parameter merge accidentally passing both.
Related errors
- ttl for snapshot must be at least
- A TTL must be greater or equal to 0, but was
- A TTL should not be negative
- A TTL should not be negative
- can't have both fixed and throttle set, choose one.
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/71dc202a601221e2.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/service/snapshot/SnapshotOptions.java:273
if (!SAFE_SNAPSHOT_NAME.matcher(resolvedSnapshotName).matches())
{
throw new IllegalArgumentException("Snapshot name contains illegal characters: " + resolvedSnapshotName + ". " +
"Allowed characters must match the pattern: " + SAFE_SNAPSHOT_NAME.pattern() +
" with a maximum of length of " + FILENAME_LENGTH + " characters.");
}
}
private void validateTTL(boolean ephemeral, DurationSpec.IntSecondsBound ttl)
{
if (ttl != null)
{
int minAllowedTtlSecs = CassandraRelevantProperties.SNAPSHOT_MIN_ALLOWED_TTL_SECONDS.getInt();
if (ttl.toSeconds() < minAllowedTtlSecs)
throw new IllegalArgumentException(format("ttl for snapshot must be at least %d seconds", minAllowedTtlSecs));
}
if (ephemeral && ttl != null)
throw new IllegalStateException(format("can not take ephemeral snapshot (%s) while ttl is specified too", tag));
}
}
@Override
public String toString()
{
return "CreateSnapshotOptions{" +
"type=" + type +
", tag='" + tag + '\'' +
", ttl=" + ttl +
", creationTime=" + creationTime +
", skipFlush=" + skipFlush +
", ephemeral=" + ephemeral +
", entities=" + Arrays.toString(entities) +
'}';
}
}
View on GitHub (pinned to 88fd0f6a0e)