From 992190dcf547c6b3aeb9ff2280e65746c2f8c27e Mon Sep 17 00:00:00 2001 From: Hermia System Date: Tue, 17 Feb 2026 17:05:26 -0800 Subject: [PATCH] fix(exec/resume): require explicit selector and errors --- code-rs/exec/src/lib.rs | 74 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/code-rs/exec/src/lib.rs b/code-rs/exec/src/lib.rs index b12cbc875e2..4dac51ee4d9 100644 --- a/code-rs/exec/src/lib.rs +++ b/code-rs/exec/src/lib.rs @@ -1189,7 +1189,7 @@ async fn resolve_resume_path( args: &crate::cli::ResumeArgs, ) -> anyhow::Result> { if !args.last && args.session_id.is_none() { - return Ok(None); + anyhow::bail!("resume requires SESSION_ID or --last"); } let catalog = SessionCatalog::new(config.code_home.clone()); @@ -1199,7 +1199,10 @@ async fn resolve_resume_path( .find_by_id(id_str) .await .context("failed to look up session by id")?; - Ok(entry.map(|entry| entry_to_rollout_path(&config.code_home, &entry))) + match entry { + Some(entry) => Ok(Some(entry_to_rollout_path(&config.code_home, &entry))), + None => anyhow::bail!("no session found matching id {id_str}"), + } } else if args.last { let query = SessionQuery { cwd: None, @@ -1214,9 +1217,12 @@ async fn resolve_resume_path( .get_latest(&query) .await .context("failed to get latest session from catalog")?; - Ok(entry.map(|entry| entry_to_rollout_path(&config.code_home, &entry))) + match entry { + Some(entry) => Ok(Some(entry_to_rollout_path(&config.code_home, &entry))), + None => anyhow::bail!("no recorded sessions found to resume"), + } } else { - Ok(None) + anyhow::bail!("resume requires SESSION_ID or --last") } } @@ -3011,4 +3017,64 @@ mod tests { ); } + #[tokio::test] + async fn exec_resolve_resume_requires_selector() { + let temp = TempDir::new().unwrap(); + let config = test_config(temp.path()); + + let args = crate::cli::ResumeArgs { + session_id: None, + last: false, + prompt: None, + }; + + let err = resolve_resume_path(&config, &args) + .await + .expect_err("missing selector should error"); + assert!( + err.to_string().contains("SESSION_ID or --last"), + "unexpected error: {err}" + ); + } + + #[tokio::test] + async fn exec_resolve_by_id_errors_when_not_found() { + let temp = TempDir::new().unwrap(); + let config = test_config(temp.path()); + + let args = crate::cli::ResumeArgs { + session_id: Some("ffffffff".to_string()), + last: false, + prompt: None, + }; + + let err = resolve_resume_path(&config, &args) + .await + .expect_err("unknown id should error"); + assert!( + err.to_string().contains("no session found matching id"), + "unexpected error: {err}" + ); + } + + #[tokio::test] + async fn exec_resolve_last_errors_when_no_sessions() { + let temp = TempDir::new().unwrap(); + let config = test_config(temp.path()); + + let args = crate::cli::ResumeArgs { + session_id: None, + last: true, + prompt: None, + }; + + let err = resolve_resume_path(&config, &args) + .await + .expect_err("--last without sessions should error"); + assert!( + err.to_string().contains("no recorded sessions found to resume"), + "unexpected error: {err}" + ); + } + }