{"record":{"id":"1266e07c5ba76f40","repo":"apache/hadoop","slug":"class-name-suiteclassname-must-be-an-imple","errorCode":null,"errorMessage":"class name \" + suiteClassName + \" must be an implementation of \" + HdfsCompatSuite.class.getName()","messagePattern":"class name \" \\+ suiteClassName \\+ \" must be an implementation of \" \\+ HdfsCompatSuite\\.class\\.getName\\(\\)","errorType":"validation","errorClass":"HdfsCompatIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-compat-bench/src/main/java/org/apache/hadoop/fs/compat/common/HdfsCompatCommand.java","lineNumber":88,"sourceCode":"    Map<String, HdfsCompatSuite> defaultSuites = getDefaultSuites();\n    this.suite = defaultSuites.getOrDefault(this.suiteName, null);\n    if (this.suite != null) {\n      return;\n    }\n    String key = \"hadoop.compatibility.suite.\" + this.suiteName + \".classname\";\n    final String suiteClassName = conf.get(key, null);\n    if ((suiteClassName == null) || suiteClassName.isEmpty()) {\n      throw new HdfsCompatIllegalArgumentException(\n          \"cannot get class name for suite \" + this.suiteName +\n              \", configuration \" + key + \" is not properly set.\");\n    }\n    Constructor<?> ctor = suiteClassName.getClass().getConstructor();\n    ctor.setAccessible(true);\n    Object suiteObj = ctor.newInstance();\n    if (suiteObj instanceof HdfsCompatSuite) {\n      this.suite = (HdfsCompatSuite) suiteObj;\n    } else {\n      throw new HdfsCompatIllegalArgumentException(\n          \"class name \" + suiteClassName + \" must be an\" +\n              \" implementation of \" + HdfsCompatSuite.class.getName());\n    }\n    if (suite.getSuiteName() == null || suite.getSuiteName().isEmpty()) {\n      throw new HdfsCompatIllegalArgumentException(\n          \"suite \" + suiteClassName + \" suiteName is empty\");\n    }\n    for (HdfsCompatSuite defaultSuite : defaultSuites.values()) {\n      if (suite.getSuiteName().equalsIgnoreCase(defaultSuite.getSuiteName())) {\n        throw new HdfsCompatIllegalArgumentException(\n            \"suite \" + suiteClassName + \" suiteName\" +\n                \" conflicts with default suite \" + defaultSuite.getSuiteName());\n      }\n    }\n    if (!hasApiCase() && !hasShellCase()) {\n      throw new HdfsCompatIllegalArgumentException(\n          \"suite \" + suiteClassName + \" is empty for both API and SHELL\");\n    }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-compat-bench/src/main/java/org/apache/hadoop/fs/compat/common/HdfsCompatCommand.java#L70-L106","documentation":"After loading the class named by hadoop.compatibility.suite.<name>.classname, initSuite requires the constructed object to implement HdfsCompatSuite. Note a defect in this code path: it reflects on suiteClassName.getClass() — the Class of the java.lang.String value — and instantiates a new String, so the instanceof check can never succeed for a custom suite in this version. The intended behavior (Class.forName(suiteClassName) + no-arg constructor + instanceof) is what the message describes.","triggerScenarios":"Configuring a class that does not implement HdfsCompatSuite; or, with the current implementation, configuring any class at all, because the reflective load resolves against String.class and produces an object that always fails the instanceof check (then this exact error is thrown).","commonSituations":"First run after registering a custom suite (hits the getClass() defect); class renamed so an old FQCN no longer names a suite implementation; copy-paste of the class name with a typo.","solutions":["Verify the configured class implements org.apache.hadoop.fs.compat.common.HdfsCompatSuite and has a public no-arg constructor","If you build this module from source, fix the instantiation: use Class.forName(suiteClassName).getConstructor() instead of suiteClassName.getClass().getConstructor()","Check the FQCN in the configuration value for typos","Track/upgrade to a release where custom-suite loading is fixed"],"exampleFix":"// before: reflects on String.class, so suiteObj is a String\n// -> always \"class name ... must be an implementation of ...HdfsCompatSuite\"\nConstructor<?> ctor = suiteClassName.getClass().getConstructor();\nObject suiteObj = ctor.newInstance();\n\n// after\nClass<?> clazz = Class.forName(suiteClassName);\nConstructor<?> ctor = clazz.getConstructor();\nObject suiteObj = ctor.newInstance();","handlingStrategy":"try-catch","validationCode":"String className = conf.get(key);\nClass<?> c = Class.forName(className);\nif (!HdfsCompatSuite.class.isAssignableFrom(c)\n    || !Modifier.isPublic(c.getModifiers())) {\n  throw new IllegalArgumentException(\n      className + \" must be a public implementation of HdfsCompatSuite\");\n}\nc.getConstructor(); // NoSuchMethodException -> fail fast on missing no-arg ctor","typeGuard":"static boolean isCompatSuiteClass(Class<?> c) {\n  return HdfsCompatSuite.class.isAssignableFrom(c);\n}","tryCatchPattern":"Catch HdfsCompatIllegalArgumentException around the tool invocation; on 'must be an implementation of', verify the configured class implements HdfsCompatSuite — and note this Hadoop version's getClass()-on-String defect makes every custom suite fail here, so patch or pin a fixed build before retrying.","preventionTips":["Unit-test custom suites by loading them reflectively exactly the way HdfsCompatCommand does","Verify assignability with HdfsCompatSuite.class.isAssignableFrom(clazz) at registration time","Pin a Hadoop version where custom-suite loading is verified, or run the bench from a patched source tree"],"tags":["hadoop-compat-bench","reflection","classloading","plugin","suite-registration"],"backgroundTag":"class-instantiation-failed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}