apache/cassandra · error · InvalidRequestException

Invalid value for property '%s'. It must be a string

Error message

Invalid value for property '%s'. It must be a string

What it means

RoleOptions.validate() requires the PASSWORD option value to be a String. If the CQL term for PASSWORD parses to another type (e.g. a number or boolean literal), validate() throws InvalidRequestException stating the property must be a string.

Source

Thrown at src/java/org/apache/cassandra/auth/RoleOptions.java:154

    {
        for (Map.Entry<IRoleManager.Option, Object> option : options.entrySet())
        {
            if (!DatabaseDescriptor.getRoleManager().supportedOptions().contains(option.getKey()))
                throw new InvalidRequestException(String.format("%s doesn't support %s",
                                                                DatabaseDescriptor.getRoleManager().getClass().getName(),
                                                                option.getKey()));
            switch (option.getKey())
            {
                case LOGIN:
                case SUPERUSER:
                    if (!(option.getValue() instanceof Boolean))
                        throw new InvalidRequestException(String.format("Invalid value for property '%s'. " +
                                                                        "It must be a boolean",
                                                                        option.getKey()));
                    break;
                case PASSWORD:
                    if (!(option.getValue() instanceof String))
                        throw new InvalidRequestException(String.format("Invalid value for property '%s'. " +
                                                                        "It must be a string",
                                                                        option.getKey()));
                    if (options.containsKey(IRoleManager.Option.HASHED_PASSWORD))
                        throw new InvalidRequestException(String.format("Properties '%s' and '%s' are mutually exclusive",
                                                                        IRoleManager.Option.PASSWORD, IRoleManager.Option.HASHED_PASSWORD));
                    break;
                case HASHED_PASSWORD:
                    if (!(option.getValue() instanceof String))
                        throw new InvalidRequestException(String.format("Invalid value for property '%s'. " +
                                                                        "It must be a string",
                                                                        option.getKey()));
                    if (options.containsKey(IRoleManager.Option.PASSWORD))
                        throw new InvalidRequestException(String.format("Properties '%s' and '%s' are mutually exclusive",
                                                                        IRoleManager.Option.PASSWORD, IRoleManager.Option.HASHED_PASSWORD));
                    try
                    {
                        BCrypt.checkpw("dummy", (String) option.getValue());
                    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Quote the password: WITH PASSWORD = '12345'.
  2. In programmatic construction, put a String value into the options map for IRoleManager.Option.PASSWORD.
  3. Escape special characters in passwords per CQL string literal rules.

Example fix

// before
CREATE ROLE alice WITH PASSWORD = 12345;
// after
CREATE ROLE alice WITH PASSWORD = '12345';
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = roleOptions.get(IRoleManager.Option.PASSWORD);
if (v != null && !(v instanceof String))
    throw new IllegalArgumentException("PASSWORD must be a quoted CQL string");

Type guard

boolean isStringOption(Object v) { return v instanceof String; }

Try / catch

try {
    session.execute("CREATE ROLE alice WITH PASSWORD = ?", password); // driver sends String
} catch (InvalidRequestException e) {
    if (e.getMessage().contains("It must be a string")) {
        // retry with quoted string value
    }
}

Prevention

When it happens

Trigger: CREATE ROLE ... WITH PASSWORD = 12345 — the password given as an unquoted numeric literal, so it is not a String when validate() runs.

Common situations: Programmatic statement builders binding non-string values into the PASSWORD option; users writing passwords that look numeric without quotes.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/5e96e39fbb9adac8. Report an issue: GitHub.