{"record":{"id":"2b8aabcdcf38487a","repo":"apache/cassandra","slug":"there-has-to-be-one-of-s-s-specified","errorCode":null,"errorMessage":"There has to be one of %s, %s specified.","messagePattern":"There has to be one of (.+?), (.+?) specified\\.","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/auth/PasswordDefaultRoleInitializer.java","lineNumber":116,"sourceCode":"    }\n\n    @Override\n    public String defaultRoleName()\n    {\n        return role;\n    }\n\n    @Override\n    public void validateConfiguration() throws ConfigurationException\n    {\n        if (Strings.isNullOrEmpty(role))\n            throw new ConfigurationException(String.format(\"%s requires a non-empty %s parameter\", getClass().getSimpleName(), ROLE));\n\n        boolean specifiedPassword = !Strings.isNullOrEmpty(password);\n        boolean specifiedPasswordHash = !Strings.isNullOrEmpty(passwordHash);\n\n        if (!specifiedPassword && !specifiedPasswordHash)\n            throw new ConfigurationException(String.format(\"There has to be one of %s, %s specified.\", PASSWORD, PASSWORD_HASH));\n        else if (specifiedPassword && specifiedPasswordHash)\n            throw new ConfigurationException(String.format(\"Only one of %s, %s can be specified.\", PASSWORD, PASSWORD_HASH));\n    }\n\n    @VisibleForTesting\n    public String createDefaultRoleQuery()\n    {\n        return String.format(\"INSERT INTO %s.%s (role, is_superuser, can_login, salted_hash) VALUES ('%s', true, true, '%s') USING TIMESTAMP 0\",\n                             SchemaConstants.AUTH_KEYSPACE_NAME,\n                             AuthKeyspace.ROLES,\n                             escapeCqlLiteral(role),\n                             escapeCqlLiteral(password == null ? passwordHash : hashpw(password)));\n    }\n}\n","sourceCodeStart":98,"sourceCodeEnd":131,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/auth/PasswordDefaultRoleInitializer.java#L98-L131","documentation":"validateConfiguration() requires the default role to be seeded with a secret: either a plaintext password or a pre-computed salted hash must be present. If neither is specified, ConfigurationException is thrown because the created role would be unusable/unloggable.","triggerScenarios":"cassandra.yaml default role options set with role_name but neither password nor password_hash provided (both null/empty).","commonSituations":"Operators filling in role_name but forgetting the password; config generators dropping secret values from unmanaged keys; copy-pasting a partial example config.","solutions":["Add password: <plaintext> to the default role options in cassandra.yaml","Or supply password_hash: <bcrypt hash> to avoid storing plaintext in the yaml","Re-run startup config validation after the change to confirm"],"exampleFix":"// before\nrole_name: cassandra\n// after\nrole_name: cassandra\npassword_hash: $2a$10$...","handlingStrategy":"validation","validationCode":"if (isBlank(password) && isBlank(passwordHash)) fail(\"set either password or password_hash for the default role\");","typeGuard":"boolean hasSecret(Map<String,String> opts) { return notBlank(opts.get(\"password\")) || notBlank(opts.get(\"password_hash\")); }","tryCatchPattern":"try { config.validate(); } catch (ConfigurationException e) { promptForDefaultRolePassword(); }","preventionTips":["Always pair role_name with password or password_hash in auth config","Store password_hash via secrets management rather than plaintext","Diff config changes against a known-good reference yaml"],"tags":["configuration","auth","startup"],"backgroundTag":"missing-required-config-field","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"}