{"record":{"id":"dcd920df1061eddb","repo":"apache/cassandra","slug":"required-option-missing-for-index-s-s","errorCode":null,"errorMessage":"Required option missing for index %s : %s","messagePattern":"Required option missing for index (.+?) : (.+?)","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/schema/IndexMetadata.java","lineNumber":145,"sourceCode":"\n    public static String generateDefaultIndexName(String table)\n    {\n        return PATTERN_NON_WORD_CHAR.matcher(table + \"_idx\").replaceAll(\"\");\n    }\n\n    public void validate(TableMetadata table)\n    {\n        // TODO: address validating the length by CASSANDRA-20445\n        if (!isValidCharsName(name))\n            throw new ConfigurationException(\"Illegal index name \" + name);\n\n        if (kind == null)\n            throw new ConfigurationException(\"Index kind is null for index \" + name);\n\n        if (kind == Kind.CUSTOM)\n        {\n            if (options == null || !options.containsKey(IndexTarget.CUSTOM_INDEX_OPTION_NAME))\n                throw new ConfigurationException(String.format(\"Required option missing for index %s : %s\",\n                                                               name, IndexTarget.CUSTOM_INDEX_OPTION_NAME));\n\n            // Get the fully qualified class name:\n            String className = getIndexClassName();\n\n            Class<? extends Index> indexerClass = FBUtilities.classForNameWithoutInitialization(className, \"custom indexer\", Index.class);\n            validateCustomIndexOptions(table, indexerClass, options);\n        }\n    }\n\n    public String getIndexClassName()\n    {\n        if (isCustom())\n        {\n            String className = options.get(IndexTarget.CUSTOM_INDEX_OPTION_NAME);\n            return indexNameAliases.getOrDefault(toLowerCaseLocalized(className), className);\n        }\n        return CassandraIndex.class.getName();","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/schema/IndexMetadata.java#L127-L163","documentation":"For CUSTOM indexes, IndexMetadata.validate requires the 'class_name' option (IndexTarget.CUSTOM_INDEX_OPTION_NAME) in the index options map so it can load the custom Index implementation class. Missing 'class_name' means Cassandra has no implementation to instantiate.","triggerScenarios":"Creating a custom index without 'class_name' in the OPTIONS map (or with options null), then validate(TableMetadata) is called during schema creation.","commonSituations":"CREATE CUSTOM INDEX without the OPTIONS = {'class_name': '...'} clause; tooling that builds custom IndexMetadata but drops the options map.","solutions":["Add OPTIONS = {'class_name': 'com.example.YourIndex'} to the CREATE CUSTOM INDEX statement","Ensure programmatic builders put IndexTarget.CUSTOM_INDEX_OPTION_NAME in the options map","Use a non-CUSTOM index kind if you do not have a custom indexer class"],"exampleFix":"// before\nCREATE CUSTOM INDEX my_idx ON ks.t (col); // no options\n// after\nCREATE CUSTOM INDEX my_idx ON ks.t (col) USING 'org.apache.cassandra.index.sasi.SASIIndex' WITH OPTIONS = {'mode': 'CONTAINS'};","handlingStrategy":"validation","validationCode":"if (kind == Kind.CUSTOM && (options == null || !options.containsKey(\"class_name\"))) throw new IllegalArgumentException(\"custom index requires class_name option\");","typeGuard":null,"tryCatchPattern":"try { index.validate(table); } catch (ConfigurationException e) { log.error(\"custom index missing class_name\", e); }","preventionTips":["Always include OPTIONS = {'class_name': '...'} with CREATE CUSTOM INDEX","Ensure builders populate IndexTarget.CUSTOM_INDEX_OPTION_NAME for CUSTOM kind","Verify the class_name points to a class implementing org.apache.cassandra.index.Index"],"tags":["index","custom-index","validation"],"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"}