{"record":{"id":"ccb998134961a1d7","repo":"risingwavelabs/risingwave","slug":"replace-sink-into-table-is-not-supported","errorCode":null,"errorMessage":"replace sink into table is not supported","messagePattern":"replace sink into table is not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/meta/src/controller/streaming_job.rs","lineNumber":528,"sourceCode":"                .and_then(|(sink, object)| object.map(|object| (sink, object)))\n                .ok_or_else(|| MetaError::catalog_id_not_found(\"sink\", *old_sink_id))?;\n            let old_streaming_job = StreamingJobModel::find_by_id(old_sink_id.as_job_id())\n                .one(&txn)\n                .await?\n                .ok_or_else(|| MetaError::catalog_id_not_found(\"sink\", *old_sink_id))?;\n            if old_object.obj_type != ObjectType::Sink\n                || old_object.database_id != Some(sink.database_id)\n                || old_object.schema_id != Some(sink.schema_id)\n                || old_sink.name != sink.name\n            {\n                bail!(\n                    \"old sink {} does not match replacement sink {}\",\n                    old_sink_id,\n                    sink.name\n                );\n            }\n            if old_sink.target_table.is_some() || sink.target_table.is_some() {\n                bail!(\"replace sink into table is not supported\");\n            }\n            if old_streaming_job.job_status != JobStatus::Created {\n                bail!(\"sink {} is not ready to be replaced\", old_sink_id);\n            }\n        } else {\n            check_relation_name_duplicate(\n                &streaming_job.name(),\n                streaming_job.database_id(),\n                streaming_job.schema_id(),\n                &txn,\n            )\n            .await?;\n        }\n\n        // check if any dependency is in altering status.\n        if !dependencies.is_empty() {\n            let altering_cnt = ObjectDependency::find()\n                .join(","sourceCodeStart":510,"sourceCodeEnd":546,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/controller/streaming_job.rs#L510-L546","documentation":"Guard in create_job_catalog during sink replacement (`ALTER ... REPLACE`): the object being replaced is configured as a sink-into-table replacement, which the meta service does not support, so job catalog creation for the replacement fails.","triggerScenarios":"create_job_catalog with replace_sink where old_sink.target_table is Some or the new sink's target_table is Some.","commonSituations":"User attempts CREATE SINK ... REPLACE on a sink created with `INTO table`, or replaces a plain sink with a sink-into-table sink.","solutions":["Drop the sink-into-table sink and create the new sink separately instead of using REPLACE.","Ensure both old and new sinks are external (non-table-target) sinks when using replace.","Split the operation: drop old sink, then CREATE SINK INTO TABLE if that is the goal."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"-- check the old sink is not sink-into-table\nSELECT s.target_table IS NOT NULL AS into_table\nFROM rw_sinks s WHERE s.id = <old_sink_id>;","typeGuard":null,"tryCatchPattern":"if let Err(e) = catalog.create_job_catalog(job).await {\n    if e.to_string().contains(\"replace sink into table is not supported\") {\n        // fall back to DROP SINK + CREATE SINK\n    }\n}","preventionTips":["Never use REPLACE for sinks created with INTO table","Document replace-support limits in DDL tooling"],"tags":["meta","sink","replace"],"backgroundTag":"unsupported-operation","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"}