risingwavelabs/risingwave · error · ConnectorError
the key {} is set both in plaintext and secret
Error message
the key {} is set both in plaintext and secret What it means
When updating a source's properties, each key may be changed either as a plaintext property or as a secret reference, but not both at once. handle_update iterates the plaintext update map and rejects any key that also appears in the secret-reference map, since the two would conflict and the final value would be ambiguous.
Source
Thrown at src/connector/src/with_options.rs:289
&self.secret_ref
}
pub fn handle_update(
&mut self,
update_alter_props: BTreeMap<String, String>,
update_alter_secret_refs: BTreeMap<String, PbSecretRef>,
) -> ConnectorResult<(Vec<SecretId>, Vec<SecretId>)> {
let old_secret_ids = self
.secret_ref
.values()
.map(|secret_ref| secret_ref.secret_id)
.collect::<BTreeSet<_>>();
// make sure the key in update_alter_props and update_alter_secret_refs not collide
for key in update_alter_props.keys() {
if update_alter_secret_refs.contains_key(key) {
return Err(
anyhow::anyhow!("the key {} is set both in plaintext and secret", key).into(),
);
}
}
// remove legacy key if it's set in both plaintext and secret
// When a property changes from secret to plaintext, remove the old secret dependency
for k in update_alter_props.keys() {
self.secret_ref.remove(k);
}
// Handle secret ref updates
for k in update_alter_secret_refs.keys() {
// Remove any plaintext value for this key
self.inner.remove(k);
}
self.inner.extend(update_alter_props);
self.secret_ref.extend(update_alter_secret_refs);View on GitHub (pinned to 6469eb736d)
Solutions
- Remove the duplicate key from either the plaintext update or the secret-ref update so each key appears in exactly one map
- To move a key from secret to plaintext (or back), update only the target form in a single ALTER
- Split conflicting changes into sequential statements
Example fix
// before ALTER SOURCE s SET properties.access_key='abc' WITH(secret_ref_access_key='secret-1') // after ALTER SOURCE s WITH(secret_ref_access_key='secret-1')
Defensive patterns
Strategy: validation
Validate before calling
function validateNoPlaintextSecretCollision(plainProps, secretRefs) {
for (const k of Object.keys(plainProps)) {
if (k in secretRefs) throw new Error(`key ${k} set both in plaintext and secret`);
}
} Type guard
const hasNoCollision = (p, s) => !Object.keys(p).some(k => k in s);
Try / catch
try { handleUpdate(plainUpdates, secretUpdates); } catch (e) { if (String(e).includes('set both in plaintext and secret')) { dropDuplicateKeyAndRetry(); } else { throw e; } } Prevention
- Decide per key whether it lives in plaintext or secret and change only that form
- Deduplicate ALTER statements before applying property updates
- When migrating keys between plaintext and secret, issue a single update targeting the new form only
When it happens
Trigger: Calling handle_update (via ALTER SOURCE ... or update_source_props_by_source_id / update_connection_and_dependent_objects_props) where an ALTER supplies the same key both as a plain property and as a secret_ref, e.g. setting 'access_key' in WITH properties and also as a secret reference in the same statement.
Common situations: Migrating a property from plaintext to secret (or vice versa) by specifying both forms in one statement instead of changing only one; tooling that appends properties without deduplicating against secret refs.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- secret_store_private_key is not configured
- secret_store_private_key is not configured
- No auth method specified for Vault backend
- Field '{}' not found in secret
- unrecognized configs: {:?}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/f9137ca20326bb74.
Report an issue: GitHub.