{"record":{"id":"90b0ae327405324d","repo":"risingwavelabs/risingwave","slug":"exactly-one-of-job-id-or-fragment-id-must-be-provi","errorCode":null,"errorMessage":"exactly one of job_id or fragment_id must be provided","messagePattern":"exactly one of job_id or fragment_id must be provided","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/ctl/src/cmd_impl/meta/resume_backfill.rs","lineNumber":31,"sourceCode":"// limitations under the License.\n\nuse anyhow::{Result, anyhow};\nuse risingwave_pb::ddl_service::RisectlResumeBackfillRequest;\nuse risingwave_pb::ddl_service::risectl_resume_backfill_request::Target;\nuse risingwave_pb::id::{FragmentId, JobId};\n\nuse crate::CtlContext;\n\npub async fn resume_backfill(\n    context: &CtlContext,\n    job_id: Option<JobId>,\n    fragment_id: Option<FragmentId>,\n) -> Result<()> {\n    let target = match (job_id, fragment_id) {\n        (Some(job_id), None) => Target::JobId(job_id),\n        (None, Some(fragment_id)) => Target::FragmentId(fragment_id),\n        _ => {\n            return Err(anyhow!(\n                \"exactly one of job_id or fragment_id must be provided\"\n            ));\n        }\n    };\n\n    let meta_client = context.meta_client().await?;\n    meta_client\n        .risectl_resume_backfill(RisectlResumeBackfillRequest {\n            target: Some(target),\n        })\n        .await?;\n    println!(\"Done.\");\n    Ok(())\n}\n","sourceCodeStart":13,"sourceCodeEnd":46,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/ctl/src/cmd_impl/meta/resume_backfill.rs#L13-L46","documentation":"Guard in risectl resume_backfill: exactly one of job_id or fragment_id must be supplied. Passing both, or neither, leaves no unambiguous protobuf Target to build, so the command fails with this error instead of guessing which backfill to resume.","triggerScenarios":"Calling the resume-backfill command with both job_id and fragment_id set, or with both omitted (None, None).","commonSituations":"CLI wrapper passing defaults for both flags; scripting that fills both options unconditionally.","solutions":["Pass exactly one of --job-id or --fragment-id","If both are set in a script, clear the unwanted one to None/omit the flag"],"exampleFix":"// before\nresume_backfill(ctx, Some(job_id), Some(fragment_id))\n// after\nresume_backfill(ctx, Some(job_id), None)","handlingStrategy":"validation","validationCode":"match (job_id.is_some(), fragment_id.is_some()) {\n    (true, false) | (false, true) => {},\n    _ => return Err(anyhow!(\"provide exactly one of job_id or fragment_id\")),\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass only one of the two flags","In wrappers, default both to None and set only the user-supplied one"],"tags":["rust","risingwave","cli","argument-validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}