{"record":{"id":"069adeab183c79a9","repo":"risingwavelabs/risingwave","slug":"some-streaming-jobs-already-exist-in-meta-please","errorCode":null,"errorMessage":"Some streaming jobs already exist in meta, please start with recovery enabled or clean up the metadata using `./risedev clean-data`","messagePattern":"Some streaming jobs already exist in meta, please start with recovery enabled or clean up the metadata using `\\./risedev clean-data`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/meta/src/barrier/worker.rs","lineNumber":381,"sourceCode":"\n    /// Start an infinite loop to take scheduled barriers and send them.\n    async fn run(mut self, shutdown_rx: Receiver<()>) {\n        tracing::info!(\n            \"Starting barrier manager with: enable_recovery={}, in_flight_barrier_nums={}\",\n            self.enable_recovery,\n            self.checkpoint_control.in_flight_barrier_nums,\n        );\n\n        if !self.enable_recovery {\n            let job_exist = self\n                .context\n                .metadata_manager\n                .catalog_controller\n                .has_any_streaming_jobs()\n                .await\n                .unwrap();\n            if job_exist {\n                panic!(\n                    \"Some streaming jobs already exist in meta, please start with recovery enabled \\\n                or clean up the metadata using `./risedev clean-data`\"\n                );\n            }\n        }\n\n        {\n            // Bootstrap recovery. Here we simply trigger a recovery process to achieve the\n            // consistency.\n            // Even if there's no actor to recover, we still go through the recovery process to\n            // inject the first `Initial` barrier.\n            let span = tracing::info_span!(\"bootstrap_recovery\");\n            crate::telemetry::report_event(\n                risingwave_pb::telemetry::TelemetryEventStage::Recovery,\n                \"normal_recovery\",\n                0,\n                None,\n                None,","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/barrier/worker.rs#L363-L399","documentation":"At startup, the barrier manager checks whether the metadata store already contains streaming jobs. If `has_any_streaming_jobs()` is true while recovery is disabled, it panics with a message telling the operator to either start with recovery enabled or clean the metadata, because leftover streaming jobs cannot run without a recovery-capable barrier manager.","triggerScenarios":"Starting the meta node with recovery disabled (e.g. a config/profile where state store or recovery is off) against a metadata store that retains streaming jobs from a previous run — the panic occurs during `run` (invoked from `start`) before serving traffic.","commonSituations":"Reusing a persistent metadata directory ( Hummock/meta state) after a previous run with jobs; switching a dev profile from recovery-enabled to recovery-disabled; forgetting `./risedev clean-data` between experiments.","solutions":["Enable recovery in the config (recovery mode / recovery-enabled) and restart, so existing jobs are recovered.","If the data is disposable, run `./risedev clean-data` (or wipe the meta/state store) and start fresh.","Do NOT try to disable streaming or bypass the check; the panic is intentional to prevent silent data inconsistency."],"exampleFix":"// before: starting with recovery disabled on a dirty store\nstart_node(recovery_enabled: false) // panics\n// after (risedev)\n// ./risedev clean-data && ./risedev d\n// or in config: [meta]\n// enable_recovery = true","handlingStrategy":"validation","validationCode":"# before starting with recovery disabled, ensure the store is clean\n./risedev clean-data\n# or verify no jobs exist first\npsql -c \"SELECT count(*) FROM rw_streaming_jobs;\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always run with recovery enabled outside throwaway environments.","Run `./risedev clean-data` when switching between recovery-enabled and recovery-disabled profiles.","Never point a recovery-disabled meta node at a metadata directory used by a previous cluster."],"tags":["meta","startup","panic","recovery","metadata"],"backgroundTag":"dirty-metadata-recovery-required","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"}