apache/cassandra · error · ConfigurationException
The result of ICompressor.serializedAs(), %s, of a compresso
Error message
The result of ICompressor.serializedAs(), %s, of a compressor object created by a compressor provider %s does not match the compressor class to get a compressor for. You need to override serializedAs() method of your custom compressor and return base compressor class it is the substitute for.
What it means
When getCompressor() creates a compressor through a custom compression provider, it validates that the returned ICompressor's serializedAs() result equals the compressor class that was actually requested. A mismatch means the custom compressor would be written to the schema with a name that cannot be resolved back to the class it substitutes for, corrupting the on-disk/s-schema identity. Cassandra throws ConfigurationException so the operator fixes the provider's serializedAs() override before the name ever lands in a table schema.
Source
Thrown at src/java/org/apache/cassandra/io/compress/CompressorRegistry.java:189
if (provider.isFailOnMissingProvider())
throw t;
compressor = DEFAULT_COMPRESSION_PROVIDER.createCompressor(compressorClass, compressionOptions);
}
// Validate the masquerade target for both the provider and the fallback path: whatever is
// returned must serialize as exactly the compressor class that was requested, otherwise the
// schema / on-disk format would record a name that cannot be resolved on peers and restarts.
Class<? extends ICompressor> serializedAs = compressor.serializedAs();
if (serializedAs == null || serializedAs.getSimpleName().isEmpty())
throw new ConfigurationException(String.format("ICompressor.serializedAs() of a compressor created by provider %s returned %s. " +
"It must return a non-anonymous built-in compressor class in package " +
"org.apache.cassandra.io.compress.",
provider.getClass(),
serializedAs));
if (serializedAs != compressorClass)
throw new ConfigurationException(String.format("The result of ICompressor.serializedAs(), %s, of a compressor object created " +
"by a compressor provider %s does not match the compressor class to get a compressor for. " +
"You need to override serializedAs() method of your custom compressor and return " +
"base compressor class it is the substitute for.",
serializedAs,
provider.getClass()));
return compressor;
}
/**
* Populates the registry with compression providers specified in the configuration.
* Should be called once during initialization to ensure providers are registered and available
* for use. If a provider fails to initialize and fallback is enabled, the default provider is used.
* <p>
* Each invocation constructs fresh provider instances and re-runs {@link AbstractCompressionProvider#init}
* without tearing down any previously registered instance, so a custom provider that acquires
* resources (native memory, threads, handles) in {@code init()} must tolerate being discarded if
* this is called more than once (as tests do via {@link #reset()}).
*View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Override serializedAs() in the custom compressor class returned by your provider and return the exact built-in compressor Class it substitutes for (e.g. return LZ4Compressor.class).
- Ensure the Class returned by serializedAs() is identical (same Class object) to the compressorClass passed to getCompressor() — not just an equal-named class from another classloader.
- Confirm the returned class is a non-anonymous class in org.apache.cassandra.io.compress; anonymous classes fail the preceding null/empty check.
- If you intended the built-in implementation, remove the custom provider registration from compressor_providers and let DefaultCompressionProvider handle the algorithm.
Example fix
// before
public Class<? extends ICompressor> serializedAs() { return MyLz4Wrapper.class; }
// after
@Override
public Class<? extends ICompressor> serializedAs() { return LZ4Compressor.class; } Defensive patterns
Strategy: validation
Validate before calling
Class<? extends ICompressor> as = myCompressor.serializedAs();
if (as == null || as.getSimpleName().isEmpty() || as != requestedCompressorClass)
throw new IllegalStateException("serializedAs() must return the exact requested built-in class: " + requestedCompressorClass); Type guard
boolean isValidMasquerade(ICompressor c, Class<?> requested) {
Class<? extends ICompressor> as = c.serializedAs();
return as != null && !as.getSimpleName().isEmpty() && as == requested;
} Try / catch
try {
registry.getCompressor(LZ4Compressor.class, opts);
} catch (ConfigurationException e) {
if (e.getMessage().contains("serializedAs")) { /* fix provider's serializedAs override */ }
throw e;
} Prevention
- Always override serializedAs() in custom compressors to return the built-in class being substituted
- Unit-test that serializedAs() returns the identical Class object (not an equal class from another classloader) as the requested class
- Never return anonymous or local classes from serializedAs()
- Add a startup self-check that creates each configured compressor and asserts the masquerade contract
When it happens
Trigger: Calling CompressorRegistry.getCompressor(compressorClass, options) with a registered custom provider whose returned compressor overrides serializedAs() to a Class different from the requested compressorClass (e.g. returning the provider's own subclass or a different built-in class than the one requested).
Common situations: Writing a custom AbstractCompressionProvider that wraps or replaces LZ4/Snappy/Deflate; the author overrides serializedAs() incorrectly (or does not override it so it returns the custom class itself), then creates a table with compression options mapping to a built-in compressor key.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- compressed_read_ahead_buffer_size must be at least 256KiB (s
- commitlog_disk_access_mode =
- compressed_read_ahead_buffer_size_in_kb must be at least 256
- <ConfigurationException message>
- ListType takes exactly 1 type parameter
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/10c73c2d57742e6c.
Report an issue: GitHub.