{"record":{"id":"5e32f268d1d047b9","repo":"risingwavelabs/risingwave","slug":"both-access-key-and-secret-key-must-be-provide","errorCode":null,"errorMessage":"Both `access_key` and `secret_key` must be provided","messagePattern":"Both `access_key` and `secret_key` must be provided","errorType":"validation","errorClass":"ConnectorError","httpStatus":null,"severity":"error","filePath":"src/connector/src/connector_common/common.rs","lineNumber":159,"sourceCode":"    }\n\n    async fn build_credential_provider(&self) -> ConnectorResult<SharedCredentialsProvider> {\n        if let (Some(access_key), Some(secret_key)) =\n            (self.access_key.as_ref(), self.secret_key.as_ref())\n        {\n            Ok(SharedCredentialsProvider::new(\n                aws_credential_types::Credentials::from_keys(\n                    access_key,\n                    secret_key,\n                    self.session_token.clone(),\n                ),\n            ))\n        } else if !env_var_is_true(DISABLE_DEFAULT_CREDENTIAL) {\n            Ok(SharedCredentialsProvider::new(\n                aws_config::default_provider::credentials::default_provider().await,\n            ))\n        } else {\n            bail!(\"Both `access_key` and `secret_key` must be provided\")\n        }\n    }\n\n    async fn with_role_provider(\n        &self,\n        credential: SharedCredentialsProvider,\n    ) -> ConnectorResult<SharedCredentialsProvider> {\n        if let Some(role_name) = &self.arn {\n            let region = self.build_region().await?;\n            let mut role = AssumeRoleProvider::builder(role_name)\n                .session_name(\"RisingWave\")\n                .region(region);\n            if let Some(id) = &self.external_id {\n                role = role.external_id(id);\n            }\n            let provider = role.build_from_provider(credential).await;\n            Ok(SharedCredentialsProvider::new(provider))\n        } else {","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/connector_common/common.rs#L141-L177","documentation":"Thrown by `build_credential_provider` in connector_common/common.rs when static AWS credentials are expected but only one of `access_key`/`secret_key` is set, default credential providers are disabled (RW_DISABLE_DEFAULT_CREDENTIAL env true), and no complete static pair is available. The AWS SDK requires both parts of a static credential pair.","triggerScenarios":"Building an AWS config for a sink/source with `access_key` set but `secret_key` missing (or vice versa) while default credential chain lookup is disabled.","commonSituations":"Partial secret injection (only one key mounted), copy-pasting a config template and forgetting the secret_key line, or intentionally disabling IMDS/env default credentials then supplying incomplete static creds.","solutions":["Provide both `access_key` and `secret_key` in the connector's secret/props.","If you intend to use the environment/instance-role credential chain, do not disable default credentials (leave RW_DISABLE_DEFAULT_CREDENTIAL unset/false) and remove the partial static keys.","Check the mounted secret/parameters store entry actually contains both fields."],"exampleFix":"// before\nprops: { access_key: \"AKIA...\" } // secret_key missing\n// after\nprops: { access_key: \"AKIA...\", secret_key: \"...\" }","handlingStrategy":"validation","validationCode":"function validateAwsStaticCreds(props) {\n  const hasAk = !!props.access_key, hasSk = !!props.secret_key;\n  if (hasAk !== hasSk) throw new Error('access_key and secret_key must both be set (or both omitted)');\n}\nvalidateAwsStaticCreds(withProps);","typeGuard":"const hasPair = (p) => typeof p.access_key === 'string' && p.access_key.length > 0 && typeof p.secret_key === 'string' && p.secret_key.length > 0;","tryCatchPattern":"try { await createSink(cfg); } catch (e) { if (String(e).includes('Both `access_key` and `secret_key`')) { fixSecrets(cfg); return createSink(cfg); } throw e; }","preventionTips":["Store access_key and secret_key together in one secret/parameter-set so they deploy atomically.","Never set one half of the pair; use the default credential chain if you have neither.","Check RW_DISABLE_DEFAULT_CREDENTIAL before relying on instance roles."],"tags":["aws","credentials","authentication","config"],"backgroundTag":"missing-credentials","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}