apache/hadoop · error · IllegalArgumentException
Class-name comparators are not enabled (set tfile.comparator
Error message
Class-name comparators are not enabled (set tfile.comparator.jclass.enabled=true to allow): {comparator} What it means
IllegalArgumentException from TFileMeta.makeComparator when the comparator name stored in the file starts with "jclass:" but the Configuration does not set tfile.comparator.jclass.enabled (default false). The comparator name comes from untrusted file metadata; instantiating an arbitrary class from it is a class-loading gadget, so the reflective path is opt-in. This guard only fires on files that declare a Java-class comparator.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/file/tfile/TFile.java:2100
static BytesComparator makeComparator(String comparator) {
return makeComparator(comparator, new Configuration());
}
@SuppressWarnings("unchecked")
static BytesComparator makeComparator(String comparator,
Configuration conf) {
if (comparator.length() == 0) {
// unsorted keys
return null;
}
if (comparator.equals(COMPARATOR_MEMCMP)) {
// default comparator
return new BytesComparator(new MemcmpRawComparator());
} else if (comparator.startsWith(COMPARATOR_JCLASS)) {
if (!conf.getBoolean(TFILE_COMPARATOR_JCLASS_ENABLED,
TFILE_COMPARATOR_JCLASS_ENABLED_DEFAULT)) {
throw new IllegalArgumentException(
"Class-name comparators are not enabled (set "
+ TFILE_COMPARATOR_JCLASS_ENABLED + "=true to allow): "
+ comparator);
}
String compClassName =
comparator.substring(COMPARATOR_JCLASS.length()).trim();
try {
// Resolve without running the class initializer, confirm it really
// is a RawComparator, and only then load and construct it.
Class<?> compClass =
Class.forName(compClassName, false, conf.getClassLoader());
RawComparator<Object> rawComparator =
(RawComparator<Object>) compClass.asSubclass(RawComparator.class)
.getDeclaredConstructor().newInstance();
return new BytesComparator(rawComparator);
} catch (Exception e) {
throw new IllegalArgumentException(
"Failed to instantiate comparator: " + comparator + "("View on GitHub (pinned to 2add963021)
Solutions
- Only if you trust the file's origin: conf.setBoolean("tfile.comparator.jclass.enabled", true) on the exact Configuration handed to TFile.Reader/Writer.
- Prefer rewriting the data with the standard "memcmp" comparator so no reflective loading is ever needed.
- If jclass support is required fleet-wide, set the key in the job/cluster configuration and restrict who can write TFiles, since the flag re-opens a remote classloading vector.
Example fix
// before Configuration conf = new Configuration(); TFile.Reader r = new TFile.Reader(in, len, conf); // IAE: jclass comparators disabled // after Configuration conf = new Configuration(); conf.setBoolean(TFile.TFILE_COMPARATOR_JCLASS_ENABLED, true); // trusted files only TFile.Reader r = new TFile.Reader(in, len, conf);
Defensive patterns
Strategy: validation
Validate before calling
Configuration conf = new Configuration();
// only for files from a trusted producer that declares a jclass comparator
if (isTrustedProducer(path) && needsJClassComparator(path)) {
conf.setBoolean(TFile.TFILE_COMPARATOR_JCLASS_ENABLED, true);
}
TFile.Reader r = new TFile.Reader(in, len, conf); Try / catch
try {
TFile.Reader r = new TFile.Reader(in, len, conf);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("tfile.comparator.jclass.enabled")) { /* set flag if trusted, else rewrite file */ }
else throw e;
} Prevention
- Prefer memcmp TFiles; use jclass comparators only where ordering logic demands it.
- Set the flag in job config, not ad-hoc code, so its security impact is auditable.
- Remember the flag is read from the Configuration passed to the Reader/Writer constructor.
When it happens
Trigger: Opening a TFile written with a 'jclass:com.foo.MyComparator' comparator while the reader's Configuration leaves tfile.comparator.jclass.enabled unset/false. Both the Writer constructor and the Reader path run makeComparator, so writing such a file needs the same flag.
Common situations: Default-hardened clusters reading older pre-hardening files that embedded jclass comparators; jobs where the writer node had the flag set but the reader job's configuration does not; security review forcing the flag off and legacy files failing immediately after.
Related errors
- Unsupported comparator: {comparator}
- Failed to instantiate comparator: {comparator}({e})
- Could not instantiate KeyProvider for uri: ${providerUri}
- KeyProvider ${keyProvider} was found but it is a transient p
- Errors on getting mount table loader class. The fs.viewfs.mo
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/6492dec91e464a43.
Report an issue: GitHub.