{"record":{"id":"d9b55cebf1361b16","repo":"apache/cassandra","slug":"missing-sub-option-s-for-the-s-option","errorCode":null,"errorMessage":"Missing sub-option '%s' for the '%s' option","messagePattern":"Missing sub-option '(.+?)' for the '(.+?)' option","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/schema/CompactionParams.java","lineNumber":301,"sourceCode":"\n    public boolean onlyPurgeRepairedTombstones()\n    {\n        return onlyPurgeRepairedTombstones;\n    }\n\n    public boolean isEnabled()\n    {\n        return isEnabled;\n    }\n\n    public static CompactionParams fromMap(Map<String, String> map)\n    {\n        Map<String, String> options = new HashMap<>(map);\n\n        String className = options.remove(Option.CLASS.toString());\n        if (className == null)\n        {\n            throw new ConfigurationException(format(\"Missing sub-option '%s' for the '%s' option\",\n                                                    Option.CLASS,\n                                                    TableParams.Option.COMPACTION));\n        }\n\n        return create(classFromName(className), options);\n    }\n\n    public static Class<? extends AbstractCompactionStrategy> classFromName(String name)\n    {\n        String className = name.contains(\".\")\n                         ? name\n                         : \"org.apache.cassandra.db.compaction.\" + name;\n        return FBUtilities.classForNameWithoutInitialization(className, \"compaction strategy\", AbstractCompactionStrategy.class);\n    }\n\n    /*\n     * LCS doesn't, STCS and DTCS do\n     */","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/schema/CompactionParams.java#L283-L319","documentation":"When parsing a compaction options map, CompactionParams.fromMap requires a 'class' sub-option naming the compaction strategy. If it is absent, a ConfigurationException is thrown, since Cassandra cannot determine which ICompactionStrategy to instantiate.","triggerScenarios":"ALTER TABLE ... WITH compaction = {'min_threshold': '4'} (no 'class' key); programmatic fromMap calls on maps that only carry tuning options.","commonSituations":"Hand-written DDL omitting the class; tooling that merges option maps and drops the class key; users confusing compression and compaction option shapes.","solutions":["Add the strategy class, e.g. compaction = {'class': 'SizeTieredCompactionStrategy', 'min_threshold': '4'}","Ensure tooling preserves the 'class' key when transforming option maps","Use fully qualified class names (org.apache.cassandra.db.compaction.*) for custom strategies"],"exampleFix":"// before\ncompaction = {'min_threshold': '4'}\n// after\ncompaction = {'class': 'SizeTieredCompactionStrategy', 'min_threshold': '4'}","handlingStrategy":"validation","validationCode":"if (!compactionMap.containsKey(\"class\"))\n    throw new IllegalArgumentException(\"compaction map requires a 'class' sub-option\");","typeGuard":"boolean hasCompactionClass(Map<String,String> m) { return m != null && m.containsKey(\"class\") && !m.get(\"class\").trim().isEmpty(); }","tryCatchPattern":"try { compactionParams = CompactionParams.fromMap(map); } catch (ConfigurationException e) { if (e.getMessage().contains(\"Missing sub-option\")) { /* add class key */ } throw e; }","preventionTips":["Always include the strategy class in compaction maps","Ensure map-merging utilities preserve the 'class' key","Use full class names for custom strategies"],"tags":["cassandra","schema","compaction"],"backgroundTag":"missing-required-option","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}