{"record":{"id":"c9e1564e6f05f04b","repo":"apache/cassandra","slug":"cannot-specify-s-as-a-custom-option","errorCode":null,"errorMessage":"Cannot specify %s as a CUSTOM option","messagePattern":"Cannot specify (.+?) as a CUSTOM option","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/IndexAttributes.java","lineNumber":60,"sourceCode":"    {\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;\n    }\n\n    public Map<String, String> getOptions() throws SyntaxException\n    {\n        Map<String, String> options = new HashMap<>(getRawOptions());\n        options.put(IndexTarget.CUSTOM_INDEX_OPTION_NAME, customClass);","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/IndexAttributes.java#L42-L78","documentation":"When creating/altering a CUSTOM index, Cassandra reserves the internal option key `class_name` (IndexTarget.CUSTOM_INDEX_OPTION_NAME) for itself; it is set via the `USING` clause, not via OPTIONS. Supplying `class_name` inside the OPTIONS map is ambiguous and rejected with InvalidRequestException during IndexAttributes.validate().","triggerScenarios":"CREATE CUSTOM INDEX ... USING '...' WITH OPTIONS = {'class_name': '...'} — the reserved key appears in the raw options map.","commonSituations":"Migrating from Cassandra 2.x-era SASI/third-party DDL where class_name was spelled inside options; LLM/ORM-generated CQL duplicating the USING class into OPTIONS.","solutions":["Remove the 'class_name' key from the OPTIONS map","Keep the index class only in the USING '<class>' clause"],"exampleFix":"// before\nCREATE CUSTOM INDEX ON t (c) USING 'com.x.Idx' WITH OPTIONS = {'class_name': 'com.x.Idx'};\n// after\nCREATE CUSTOM INDEX ON t (c) USING 'com.x.Idx' WITH OPTIONS = {'mode': 'CONTAINS'};","handlingStrategy":"validation","validationCode":"const opts = parseOptions(ddl);\nif (opts.class_name !== undefined) throw new Error(\"Remove reserved key 'class_name' from OPTIONS; use USING clause\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat 'class_name' and 'target' as reserved keys in index OPTIONS","Always specify custom index class via USING '<class>'","Sanitize user-provided option maps before emitting CQL"],"tags":["cql","index","reserved-keyword"],"backgroundTag":"invalid-argument-value","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"}