{"record":{"id":"851ceb45ffd1b0d0","repo":"risingwavelabs/risingwave","slug":"missing-format-encode-851ceb","errorCode":null,"errorMessage":"missing FORMAT ... ENCODE ...","messagePattern":"missing FORMAT \\.\\.\\. ENCODE \\.\\.\\.","errorType":"validation","errorClass":"SinkError::Config","httpStatus":null,"severity":"error","filePath":"src/connector/src/sink/redis.rs","lineNumber":298,"sourceCode":"\n#[async_trait]\nimpl TryFrom<SinkParam> for RedisSink {\n    type Error = SinkError;\n\n    fn try_from(param: SinkParam) -> std::result::Result<Self, Self::Error> {\n        let Some(pk_indices) = param.downstream_pk.clone() else {\n            return Err(SinkError::Config(anyhow!(\n                \"Redis Sink Primary Key must be specified.\"\n            )));\n        };\n        let config = RedisConfig::from_btreemap(param.properties.clone())?;\n        Ok(Self {\n            config,\n            schema: param.schema(),\n            pk_indices,\n            format_desc: param\n                .format_desc\n                .ok_or_else(|| SinkError::Config(anyhow!(\"missing FORMAT ... ENCODE ...\")))?,\n            db_name: param.db_name,\n            sink_from_name: param.sink_from_name,\n        })\n    }\n}\n\nimpl Sink for RedisSink {\n    type LogSinker = AsyncTruncateLogSinkerOf<RedisSinkWriter>;\n\n    const SINK_NAME: &'static str = \"redis\";\n\n    crate::impl_validate_sink_unknown_fields!();\n\n    async fn new_log_sinker(&self, _writer_param: SinkWriterParam) -> Result<Self::LogSinker> {\n        Ok(RedisSinkWriter::new(\n            self.config.clone(),\n            self.schema.clone(),\n            self.pk_indices.clone(),","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/sink/redis.rs#L280-L316","documentation":"Like the Pulsar sink, the Redis sink constructor requires a FORMAT ... ENCODE declaration (param.format_desc) to select the row formatter. When SinkParam carries no format description, the constructor returns SinkError::Config with 'missing FORMAT ... ENCODE ...'. Without it the sink cannot serialize rows for Redis.","triggerScenarios":"Building a RedisSink from a SinkParam whose format_desc is None — a CREATE SINK for connector='redis' without a FORMAT ... ENCODE ... clause, or programmatic SinkParam construction that skipped format_desc.","commonSituations":"Omitting FORMAT APPEND ONLY ENCODE JSON (or DEBEZIUM/etc.) from the DDL; copying an example that lacked the format line; tests constructing SinkParam directly without format_desc.","solutions":["Append a FORMAT ... ENCODE ... clause to the CREATE SINK statement, e.g. FORMAT APPEND ONLY ENCODE JSON.","Verify the chosen format/encode combination is supported by the Redis sink in your RisingWave version.","When constructing SinkParam programmatically, set format_desc to a valid SinkFormatDesc before calling RedisSink::try_from."],"exampleFix":"// before\nCREATE SINK s FROM mv WITH (connector='redis', url='...', primary_key='id');\n// after\nCREATE SINK s FROM mv WITH (connector='redis', url='...', primary_key='id') FORMAT APPEND ONLY ENCODE JSON;","handlingStrategy":"validation","validationCode":"// Ensure FORMAT ... ENCODE is present before creating a redis sink\nlet ddl_l = ddl.to_lowercase();\nif !(ddl_l.contains(\"format\") && ddl_l.contains(\"encode\")) {\n    return Err(\"redis sink requires FORMAT ... ENCODE ... clause\".into());\n}","typeGuard":"fn has_format_desc(param: &SinkParam) -> bool { param.format_desc.is_some() }","tryCatchPattern":"match RedisSink::try_from(param) {\n    Err(SinkError::Config(e)) if e.to_string().contains(\"missing FORMAT\") => {\n        eprintln!(\"add FORMAT APPEND ONLY ENCODE JSON (or equivalent) to CREATE SINK\");\n    }\n    other => { /* proceed */ }\n}","preventionTips":["Always append FORMAT .. ENCODE .. to redis CREATE SINK DDL","Use FORMAT APPEND ONLY ENCODE JSON as the common default","Verify format support for the redis connector version","Set format_desc when building SinkParam in tests/tools"],"tags":["rust","redis","sink","config","sql"],"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"}