{"record":{"id":"f3fad4d56245c0b8","repo":"apache/cassandra","slug":"custom-index-requires-specifiying-the-index-class","errorCode":null,"errorMessage":"CUSTOM index requires specifiying the index class","messagePattern":"CUSTOM index requires specifiying the index class","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/IndexAttributes.java","lineNumber":51,"sourceCode":"    private static final String KW_OPTIONS = \"options\";\n\n    private static final Set<String> keywords = new HashSet<>();\n    private static final Set<String> obsoleteKeywords = new HashSet<>();\n\n    public boolean isCustom;\n    public String customClass;\n\n    static\n    {\n        keywords.add(KW_OPTIONS);\n    }\n\n    public void validate() throws RequestValidationException\n    {\n        validate(keywords, obsoleteKeywords);\n\n        if (isCustom && customClass == null)\n            throw new InvalidRequestException(\"CUSTOM index requires specifiying the index class\");\n\n        if (!isCustom && customClass != null)\n            throw new InvalidRequestException(\"Cannot specify index class for a non-CUSTOM index\");\n\n        if (!isCustom && !properties.isEmpty())\n            throw new InvalidRequestException(\"Cannot specify options for a non-CUSTOM index\");\n\n        if (getRawOptions().containsKey(IndexTarget.CUSTOM_INDEX_OPTION_NAME))\n            throw new InvalidRequestException(String.format(\"Cannot specify %s as a CUSTOM option\",\n                                                            IndexTarget.CUSTOM_INDEX_OPTION_NAME));\n\n        if (getRawOptions().containsKey(IndexTarget.TARGET_OPTION_NAME))\n            throw new InvalidRequestException(String.format(\"Cannot specify %s as a CUSTOM option\",\n                                                            IndexTarget.TARGET_OPTION_NAME));\n\n    }\n\n    private Map<String, String> getRawOptions() throws SyntaxException","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/IndexAttributes.java#L33-L69","documentation":"A custom index (`CREATE CUSTOM INDEX ... USING ...`) must name the implementation class via the `USING` clause. `IndexAttributes.validate()` throws InvalidRequestException when `isCustom` is true but `customClass` is null. (Note the message contains a long-standing typo: 'specifiying'.)","triggerScenarios":"`CREATE CUSTOM INDEX i ON t (col) WITH OPTIONS = {...}` without the `USING '<class>'` clause — the CUSTOM keyword present but no class name supplied.","commonSituations":"Hand-written DDL missing USING after adding CUSTOM; template scripts where the USING line was deleted; typos so the parser drops the class.","solutions":["Add the `USING '<index implementation class>'` clause, e.g. `USING 'org.apache.cassandra.index.sasi.SASIIndex'` or `USING 'StorageAttachedIndex'`.","If a plain (built-in) index was intended, drop the CUSTOM keyword entirely.","Check any option map for the class reference in `class_name` option usage per the intended index implementation."],"exampleFix":"-- before\nCREATE CUSTOM INDEX i ON t (col) WITH OPTIONS = {'case_sensitive':'false'};\n\n-- after\nCREATE CUSTOM INDEX i ON t (col) USING 'org.apache.cassandra.index.sasi.SASIIndex' WITH OPTIONS = {'case_sensitive':'false'};","handlingStrategy":"validation","validationCode":"if (ddl.matches(\"(?i)CREATE\\\\s+CUSTOM\\\\s+INDEX\") && !ddl.matches(\"(?i)USING\\\\s+'[^']+'\"))\n    throw new IllegalArgumentException(\"CUSTOM index requires USING '<class>'\");","typeGuard":null,"tryCatchPattern":"try { session.execute(ddl); }\ncatch (InvalidQueryException e) {\n  if (e.getMessage().contains(\"requires specifiying the index class\"))\n      throw new IllegalArgumentException(\"add USING '<implementation class>' to the custom index\", e);\n  throw e;\n}","preventionTips":["Treat CUSTOM and USING as an inseparable pair in DDL generators","Keep canonical index DDL templates with the class name parameterized","Code-review index DDL for the CUSTOM/USING combination"],"tags":["cassandra","index","ddl","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}