{"record":{"id":"d60b037445ed3ee8","repo":"risingwavelabs/risingwave","slug":"s3-configuration-is-required-for-s3-sink","errorCode":null,"errorMessage":"S3 configuration is required for S3 sink","messagePattern":"S3 configuration is required for S3 sink","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/snowflake_redshift/redshift.rs","lineNumber":316,"sourceCode":"}\n\npub enum RedShiftSinkWriter {\n    S3(SnowflakeRedshiftSinkS3Writer),\n    Jdbc(SnowflakeRedshiftSinkJdbcWriter),\n}\n\nimpl RedShiftSinkWriter {\n    pub async fn new(\n        config: RedShiftConfig,\n        is_append_only: bool,\n        writer_param: super::SinkWriterParam,\n        mut param: SinkParam,\n    ) -> Result<Self> {\n        let schema = param.schema();\n        if config.with_s3 {\n            let s3_writer = SnowflakeRedshiftSinkS3Writer::new(\n                config.s3_inner.ok_or_else(|| {\n                    SinkError::Config(anyhow!(\"S3 configuration is required for S3 sink\"))\n                })?,\n                schema,\n                is_append_only,\n                config.table,\n            )?;\n            Ok(Self::S3(s3_writer))\n        } else {\n            let (writer_schema, writer_table) = if is_append_only {\n                (config.schema.clone(), config.table.clone())\n            } else {\n                (\n                    config.intermediate_schema.clone().or(config.schema.clone()),\n                    config.cdc_table.clone().ok_or_else(|| {\n                        SinkError::Config(anyhow!(\n                            \"intermediate.table.name is required for non-append-only sink\"\n                        ))\n                    })?,\n                )","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/snowflake_redshift/redshift.rs#L298-L334","documentation":"`SnowflakeRedshiftSinkWriter::new` builds an S3-backed writer when `config.with_s3` is true; the concrete S3 connection config (`s3_inner`) must have been parsed earlier. If `with_s3` is set but `s3_inner` is None, this SinkError::Config is thrown because the writer cannot reach S3.","triggerScenarios":"Setting the s3-related flag/property so `with_s3 == true` without providing the s3 connection settings (endpoint/bucket/credentials) that populate `config.s3_inner`.","commonSituations":"Users enabling S3 staging for Snowflake/Redshift sinks but omitting s3.access/s3.secret or the s3 connection name; a connector version change that reparses properties into s3_inner.","solutions":["Provide the required S3 properties (bucket, endpoint, access/secret key) in the sink WITH clause","Create and reference an S3 CONNECTION object in RisingWave so s3_inner gets populated","If S3 is not needed, remove the s3 flag so with_s3 is false"],"exampleFix":"// before\nWITH ( connector = 'snowflake', s3_stage = 'true' )\n-- after\nWITH ( connector = 'snowflake', s3_stage = 'true', s3.bucket = 'my-bucket', s3.access_key = '...', s3.secret_key = '...' )","handlingStrategy":"validation","validationCode":"// before enabling s3 staging\nif props.get(\"s3_stage\").map(|v| v == \"true\").unwrap_or(false)\n    && !(props.contains_key(\"s3.bucket\") && props.contains_key(\"s3.access_key\")) {\n    return Err(\"S3 connection properties required when s3 staging is enabled\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Provide full S3 settings whenever s3 staging is enabled","Prefer a named S3 CONNECTION object to keep credentials centralized","Test sink creation with `CREATE SINK ... ` in a dev environment first"],"tags":["rust","risingwave","sink","s3","config"],"backgroundTag":"missing-required-config-field","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"}