apache/cassandra · error · IllegalArgumentException

Snapshot name contains illegal characters: . Allowed charact

Error message

Snapshot name contains illegal characters: . Allowed characters must match the pattern:  with a maximum of length of  characters.

What it means

SnapshotOptions.validateTag rejects a snapshot (tag) name whose characters don't match the SAFE_SNAPSHOT_NAME pattern or which exceeds FILENAME_LENGTH. Cassandra restricts snapshot names to S3-safe, shell-friendly characters and blocks '/' so path traversal like '../../mysnapshot' cannot inject into snapshot directory paths. It throws IllegalArgumentException from build() before any snapshot is taken.

Source

Thrown at src/java/org/apache/cassandra/service/snapshot/SnapshotOptions.java:257

            // we are following the max length as it is in SchemaConstants for table name.
            if (resolvedSnapshotName.length() > SchemaConstants.FILENAME_LENGTH)
            {
                throw new IllegalArgumentException(format("Snapshot name must not be more than %d characters long for " +
                                                          "resolved snapshot name (got %d characters for \"%s\")",
                                                          FILENAME_LENGTH, resolvedSnapshotName.length(), resolvedSnapshotName));
            }

            // Allowed characters are a conservative subset of the AWS S3 "Safe characters" set
            // (https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html#object-key-guidelines):
            //   0-9  a-z  A-Z  -  _  .
            // plus '+', which is not an S3 "Safe character" but can legitimately appear in system
            // snapshot names via version build metadata (e.g. an upgrade snapshot "<millis>-upgrade-5.0.4+build-...").
            // The remaining S3-safe characters (! * ' ( )) are intentionally excluded as they are
            // shell-significant and error-prone in paths, and the path separator '/' is excluded too,
            // which is what blocks traversal attempts such as "../../mysnapshot"
            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));
        }
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Remove illegal characters from the snapshot name; use only characters allowed by SAFE_SNAPSHOT_NAME (alphanumerics, hyphen, underscore, dot) and stay under the max length.
  2. Replace path-like tags with a flat name, e.g. 'daily-20260910' instead of 'daily/2026/09/10'.
  3. If generating tags programmatically, sanitize/validate with the same regex before calling build().

Example fix

// before
String tag = "snapshots/2026/09/10";
// after
String tag = "snapshots-2026-09-10";
Defensive patterns

Strategy: validation

Validate before calling

Pattern SAFE = Pattern.compile("[a-zA-Z0-9][a-zA-Z0-9_\\-]*");
if (tag == null || tag.length() > 48 || !SAFE.matcher(tag).matches())
    throw new IllegalArgumentException("Invalid snapshot tag: " + tag);

Try / catch

try { nodetoolSnapshot(tag); } catch (IllegalArgumentException e) { if (e.getMessage().contains("illegal characters")) sanitizeAndRetry(tag); else throw e; }

Prevention

When it happens

Trigger: Calling nodetool snapshot -t <tag> or TableMetadata/SnapshotOptions.builder().withTag(...) with a tag containing characters outside the allowed pattern (e.g. '/', '!', '*', quotes, spaces) or longer than FILENAME_LENGTH.

Common situations: Scripts embedding paths or timestamps with slashes into the tag; copy-pasted snapshot names with shell-significant chars; automation generating overly long tags from concatenated prefixes (e.g. upgrade snapshot names derived from version build metadata).

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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