apache/cassandra · error · IllegalArgumentException
String ' ' is not a valid UUID based sstable identifier
Error message
String '${s}' is not a valid UUID based sstable identifier What it means
UUIDBasedSSTableId.Builder.fromString parses the string form of a UUID-based sstable identifier (format: base36 groups matching ([0-9a-z]{4})_([0-9a-z]{4})_([0-9a-z]{5})([0-9a-z]{13}), 26 chars total) and throws IllegalArgumentException when the string does not match the pattern (src/java/org/apache/cassandra/io/sstable/UUIDBasedSSTableId.java:145). It is the strict parser behind SSTableId creation from filenames/stream metadata.
Solutions
- Validate the string first with UUIDBasedSSTableId.Builder.instance.isUniqueIdentifier(s) before calling fromString
- Confirm the id comes from a UUID-based sstable generation; if the file is generation-based (e.g. 'mc-1-big-Data.db'), use the legacy generation format instead
- Trim whitespace and ensure you pass only the identifier portion (26 chars, base36 groups separated by underscores)
- Check that the sstable format/identifier-type configuration matches between writer and reader nodes (sstable.identifier format changes across major versions)
Example fix
// before
SSTableId id = UUIDBasedSSTableId.Builder.instance.fromString(fileName);
// after
if (!UUIDBasedSSTableId.Builder.instance.isUniqueIdentifier(fileName)) {
throw new IllegalArgumentException("not a UUID-based sstable id: " + fileName);
}
SSTableId id = UUIDBasedSSTableId.Builder.instance.fromString(fileName); Defensive patterns
Strategy: validation
Validate before calling
if (!UUIDBasedSSTableId.Builder.instance.isUniqueIdentifier(candidate))
throw new IllegalArgumentException("invalid UUID-based sstable identifier: " + candidate); Type guard
static boolean isUuidSSTableId(String s) {
return s != null && java.util.regex.Pattern.matches("(?i)[0-9a-z]{4}_[0-9a-z]{4}_[0-9a-z]{5}[0-9a-z]{13}", s);
} Try / catch
try {
return builder.fromString(s);
} catch (IllegalArgumentException e) {
logger.warn("unparseable sstable id: {}", s);
return null;
} Prevention
- Extract exactly the identifier substring from filenames before parsing
- Handle both generation-based and UUID-based ids depending on sstable format version
- Never hand-construct identifier strings; generate them via the Builder generator
When it happens
Trigger: Calling fromString with a string that is not a UUID-based identifier: an old-generation ('generation-based') sstable filename id, a truncated/malformed id, whitespace or uppercase-incompatible chars, or a random-UUID-style identifier that doesn't fit the time-UUID base36 encoding.
Common situations: Mixing sstable identifier formats across Cassandra versions (e.g. 3.x/4.0 generation-based files vs 4.1+/5.0 UUID-based ids); parsing filenames from a different table or format manually; passing a component name or column-family directory name instead of the unique-identifier substring.
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
- Cannot parse 32-bits int value from
- Cannot parse collection value from
- Cannot parse collection value from
- Cannot parse collection value from
- Cannot parse date value from
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/5248218c6a7394f2.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/io/sstable/UUIDBasedSSTableId.java:145
@Override
public boolean isUniqueIdentifier(String str)
{
return str != null && str.length() == STRING_LEN && PATTERN.matcher(str).matches();
}
@Override
public boolean isUniqueIdentifier(ByteBuffer bytes)
{
return bytes != null && bytes.remaining() == BYTES_LEN;
}
@Override
public UUIDBasedSSTableId fromString(@Nonnull String s) throws IllegalArgumentException
{
Matcher m = PATTERN.matcher(s);
if (!m.matches())
throw new IllegalArgumentException("String '" + s + "' is not a valid UUID based sstable identifier");
long dayPart = Long.parseLong(m.group(1), 36);
long secondPart = Long.parseLong(m.group(2), 36);
long nanoPart = Long.parseLong(m.group(3), 36);
long ts = (dayPart * 86_400 + secondPart) * 10_000_000 + nanoPart;
long randomPart = Long.parseUnsignedLong(m.group(4), 36);
TimeUUID uuid = new TimeUUID(ts, randomPart);
return new UUIDBasedSSTableId(uuid);
}
@Override
public UUIDBasedSSTableId fromBytes(@Nonnull ByteBuffer bytes) throws IllegalArgumentException
{
Preconditions.checkArgument(bytes.remaining() == UUIDBasedSSTableId.BYTES_LEN, "Buffer does not have a valid number of bytes remaining. Expecting: %s but was: %s", UUIDBasedSSTableId.BYTES_LEN, bytes.remaining());
bytes = bytes.order() == ByteOrder.BIG_ENDIAN ? bytes : bytes.duplicate().order(ByteOrder.BIG_ENDIAN);
TimeUUID uuid = new TimeUUID(bytes.getLong(0), bytes.getLong(Long.BYTES));
return new UUIDBasedSSTableId(uuid);View on GitHub (pinned to 88fd0f6a0e)