{"record":{"id":"9ee5bc740a6933be","repo":"sxyazi/yazi","slug":"tab-with-id-id-not-found","errorCode":null,"errorMessage":"Tab with id {id} not found","messagePattern":"Tab with id (.+?) not found","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"yazi-actor/src/context.rs","lineNumber":32,"sourceCode":"\tpub source:    Source,\n\t#[cfg(debug_assertions)]\n\tpub backtrace: Vec<&'static str>,\n}\n\nimpl Deref for Ctx<'_> {\n\ttype Target = Core;\n\n\tfn deref(&self) -> &Self::Target { self.core }\n}\n\nimpl DerefMut for Ctx<'_> {\n\tfn deref_mut(&mut self) -> &mut Self::Target { self.core }\n}\n\nimpl<'a> Ctx<'a> {\n\tpub fn new(action: &Action, core: &'a mut Core, term: &'a mut Option<Raterm>) -> Result<Self> {\n\t\tlet tab = if let Ok(id) = action.get::<Id>(\"tab\") {\n\t\t\tcore.mgr.tabs.idx(id).ok_or_else(|| anyhow!(\"Tab with id {id} not found\"))?\n\t\t} else {\n\t\t\tcore.mgr.tabs.cursor\n\t\t};\n\n\t\tOk(Self {\n\t\t\tcore,\n\t\t\tterm,\n\t\t\ttab,\n\t\t\tlevel: 0,\n\t\t\tsource: action.source,\n\t\t\t#[cfg(debug_assertions)]\n\t\t\tbacktrace: vec![],\n\t\t})\n\t}\n\n\tpub fn with<F, T>(&mut self, tab: usize, f: F) -> T\n\twhere\n\t\tF: FnOnce(&mut Self) -> T,","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-actor/src/context.rs#L14-L50","documentation":"Ctx::new resolves the target tab for every action: if the Action carries a \"tab\" id it is looked up with core.mgr.tabs.idx(id), otherwise the current cursor tab is used. An id that matches no open tab makes construction fail with \"Tab with id {id} not found\" before the actor runs. Tab ids are only valid while that tab is alive; closing a tab invalidates previously captured ids.","triggerScenarios":"Emitting or relaying an action that includes a \"tab\" argument (e.g. relay!(mgr:...).with(\"tab\", id)) after that tab was closed, or passing an id that was never allocated by mgr.tabs. Also any deferred/queued action whose captured id goes stale before dispatch.","commonSituations":"Plugins caching a tab id from an earlier Tab event and emitting actions later; keymap or plugin snippets hardcoding a tab id; driving a yazi instance via ya-emitted actions while the user closes tabs in between.","solutions":["Drop the \"tab\" argument from the action so Ctx::new falls back to the current tab (core.mgr.tabs.cursor)","Re-read the live tab id from the latest Tab event payload instead of caching it across events","Check validity first: core.mgr.tabs.idx(id) (and tabs.len()) before constructing the action","If the tab was legitimately closed, treat the error as benign and ignore/skip the action"],"exampleFix":"// before: stale cached id\nemit!(Call(relay!(mgr:hover).with(\"tab\", cached_id)));\n\n// after: let Ctx pick the current tab\nemit!(Call(relay!(mgr:hover)));","handlingStrategy":"validation","validationCode":"// Before emitting an action with an explicit tab id:\nif core.mgr.tabs.idx(id).is_none() {\n    // stale id: fall back to the current tab\n    emit!(Call(relay!(mgr:hover)));\n    return Ok(());\n}\nemit!(Call(relay!(mgr:hover).with(\"tab\", id)));","typeGuard":"fn tab_exists(mgr: &Mgr, id: Id) -> bool { mgr.tabs.idx(id).is_some() }","tryCatchPattern":"match Ctx::new(&action, core, term) {\n    Ok(cx) => { /* run actor */ }\n    Err(e) if e.to_string().starts_with(\"Tab with id\") => { /* stale tab: drop or re-emit without `tab` */ }\n    Err(e) => return Err(e),\n}","preventionTips":["Never cache tab ids across events; read them from the current Tab payload","Omit the \"tab\" argument unless you truly must target a specific tab","Assume tab ids are invalidated by close; they are not stable handles"],"tags":["tabs","actions","plugins","stale-id"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}