{"record":{"id":"d750a16a57029bb7","repo":"apache/cassandra","slug":"cannot-specify-index-class-for-a-non-custom-index","errorCode":null,"errorMessage":"Cannot specify index class for a non-CUSTOM index","messagePattern":"Cannot specify index class for a non-CUSTOM index","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/IndexAttributes.java","lineNumber":54,"sourceCode":"    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\n    {\n        Map<String, String> options = getMap(KW_OPTIONS);\n        return options == null ? Collections.emptyMap() : options;","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/IndexAttributes.java#L36-L72","documentation":"The index class option (`USING '<class>'` / `customClass`) is only meaningful for CUSTOM indexes. Supplying a class with a non-custom `CREATE INDEX` is contradictory, so validate() rejects it with InvalidRequestException.","triggerScenarios":"`CREATE INDEX i ON t (col) USING 'SomeIndexClass';` — a USING clause without the CUSTOM keyword.","commonSituations":"Users thinking `USING` alone creates a custom index (forgot the CUSTOM keyword); copy-pasted DDL where CUSTOM was dropped; confusion between built-in 2i and custom index syntax.","solutions":["Add the CUSTOM keyword: `CREATE CUSTOM INDEX i ON t (col) USING '<class>';` if a custom index was intended.","Remove the `USING '<class>'` clause if a plain built-in secondary index was intended.","Remember custom indexes also require the class name plus, optionally, OPTIONS."],"exampleFix":"-- before\nCREATE INDEX i ON t (col) USING 'StorageAttachedIndex';\n\n-- after\nCREATE CUSTOM INDEX i ON t (col) USING 'StorageAttachedIndex';","handlingStrategy":"validation","validationCode":"boolean hasCustom = ddl.matches(\"(?i)CREATE\\\\s+CUSTOM\\\\s+INDEX\");\nboolean hasUsing  = ddl.matches(\"(?i)USING\\\\s+'[^']+'\");\nif (!hasCustom && hasUsing) throw new IllegalArgumentException(\"USING requires the CUSTOM keyword\");","typeGuard":null,"tryCatchPattern":"try { session.execute(ddl); }\ncatch (InvalidQueryException e) {\n  if (e.getMessage().contains(\"non-CUSTOM index\"))\n      throw new IllegalArgumentException(\"either drop USING or add the CUSTOM keyword\", e);\n  throw e;\n}","preventionTips":["Remember the canonical form: CREATE CUSTOM INDEX ... USING '<class>'","Lint DDL for USING appearing without CUSTOM","Copy DDL from docs/templates verbatim instead of reconstructing syntax"],"tags":["cassandra","index","ddl","conflicting-options"],"backgroundTag":"mutually-exclusive-options","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"}