{"record":{"id":"b188a2a4ecdd0141","repo":"apache/cassandra","slug":"empty-value-for-boolean-option","errorCode":null,"errorMessage":"Empty value for boolean option ''","messagePattern":"Empty value for boolean option ''","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/index/sai/analyzer/NonTokenizingOptions.java","lineNumber":151,"sourceCode":"                    break;\n                }\n\n                case ASCII:\n                {\n                    boolean boolValue = validateBoolean(entry.getValue(), ASCII);\n                    builder = builder.ascii(boolValue);\n                    break;\n                }\n            }\n        }\n        return builder.build();\n    }\n\n    private static boolean validateBoolean(String value, String option)\n    {\n        if (Strings.isNullOrEmpty(value))\n        {\n            throw new InvalidRequestException(\"Empty value for boolean option '\" + option + '\\'');\n        }\n\n        if (!value.equalsIgnoreCase(Boolean.TRUE.toString()) && !value.equalsIgnoreCase(Boolean.FALSE.toString()))\n        {\n            throw new InvalidRequestException(\"Illegal value for boolean option '\" + option + \"': \" + value);\n        }\n\n        return Boolean.parseBoolean(value);\n    }\n}\n","sourceCodeStart":133,"sourceCodeEnd":162,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/index/sai/analyzer/NonTokenizingOptions.java#L133-L162","documentation":"Thrown by NonTokenizingOptions.validateBoolean when a SAI non-tokenizing analyzer boolean option (case_sensitive, normalize, ascii) is supplied with an empty or null value in the CREATE/ALTER CUSTOM INDEX WITH OPTIONS map. Cassandra rejects it up-front as an InvalidRequestException because a boolean option must be literally 'true' or 'false'.","triggerScenarios":"Executing CREATE CUSTOM INDEX ... USING 'StorageAttachedIndex' WITH OPTIONS = {'case_sensitive': ''} (or normalize/ascii with an empty string or null value); the options map reaches NonTokenizingOptions.fromMap which calls validateBoolean.","commonSituations":"Programmatic index-option builders that append a key with an unset/empty value; template-generated CQL where a variable failed to interpolate; hand-edited schema files leaving 'option': '' behind.","solutions":["Supply an explicit value: {'case_sensitive': 'true'} (or 'false')","Remove the option key entirely to accept the default","If options are built in code, skip entries whose value is null or empty before passing the map","Validate the options map client-side before issuing the CQL statement"],"exampleFix":"// before\nCREATE CUSTOM INDEX ON ks.tbl (col) USING 'StorageAttachedIndex'\n  WITH OPTIONS = {'case_sensitive': ''};\n// after\nCREATE CUSTOM INDEX ON ks.tbl (col) USING 'StorageAttachedIndex'\n  WITH OPTIONS = {'case_sensitive': 'true'};","handlingStrategy":"validation","validationCode":"Map<String,String> opts = ...; // entry CQL options\nif (opts.containsKey(\"case_sensitive\") && (opts.get(\"case_sensitive\") == null || opts.get(\"case_sensitive\").isEmpty()))\n    throw new IllegalArgumentException(\"case_sensitive requires 'true' or 'false'\");","typeGuard":null,"tryCatchPattern":"try { session.execute(createIndexCql); }\ncatch (InvalidRequestException e) {\n    if (e.getMessage().startsWith(\"Empty value for boolean option\")) { /* fix option value and retry */ }\n    else throw e;\n}","preventionTips":["Never emit an option key without a value","Filter null/empty entries from options maps before building CQL","Keep option values in constants (\"true\"/\"false\") instead of inline strings"],"tags":["cassandra","cql","sai","index-options","validation"],"backgroundTag":"empty-required-field","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"}