{"record":{"id":"7059fd62e20480ee","repo":"jackwener/OpenCLI","slug":"opencli-failed-to-recover-drifted-tab-moveerr","errorCode":null,"errorMessage":"[opencli] Failed to recover drifted tab: ${moveErr}","messagePattern":"\\[opencli\\] Failed to recover drifted tab: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"extension/src/background.ts","lineNumber":1816,"sourceCode":"      timedOut = true;\n      console.warn(`[opencli] Navigate to ${targetUrl} timed out after 15s`);\n      finish();\n    }, 15000);\n  });\n\n  let tab = await chrome.tabs.get(tabId);\n\n  // Post-navigation drift detection: if the tab moved to another window\n  // during navigation (e.g. a tab-management extension regrouped it),\n  // try to move it back to maintain session isolation.\n  const postNavigationSession = automationSessions.get(leaseKey);\n  if (postNavigationSession && tab.windowId !== postNavigationSession.windowId) {\n    console.warn(`[opencli] Tab ${tabId} drifted to window ${tab.windowId} during navigation, moving back to ${postNavigationSession.windowId}`);\n    try {\n      await chrome.tabs.move(tabId, { windowId: postNavigationSession.windowId, index: -1 });\n      tab = await chrome.tabs.get(tabId);\n    } catch (moveErr) {\n      console.warn(`[opencli] Failed to recover drifted tab: ${moveErr}`);\n    }\n  }\n\n  return pageScopedResult(cmd.id, tabId, { title: tab.title, url: tab.url, timedOut });\n}\n\nasync function handleTabs(cmd: Command, leaseKey: string): Promise<Result> {\n  const session = automationSessions.get(leaseKey);\n  if (session && !session.owned && cmd.op !== 'list') {\n    return {\n      id: cmd.id,\n      ok: false,\n      errorCode: 'bound_tab_mutation_blocked',\n      error: `Session \"${session.session}\" is bound to a user tab; tab new/select/close requires an owned OpenCLI session.`,\n      errorHint: 'Unbind the session first, or use a different session for owned OpenCLI tabs.',\n    };\n  }\n  switch (cmd.op) {","sourceCodeStart":1798,"sourceCodeEnd":1834,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/extension/src/background.ts#L1798-L1834","documentation":"Companion warning to the drift-detection warning: after detecting that a tab drifted to a different window during navigation, the chrome.tabs.move back to the session window (or the follow-up chrome.tabs.get) failed. The code catches moveErr and logs it rather than throwing, then continues using the tab wherever it currently is. Session window isolation may be broken for the remainder of the command.","triggerScenarios":"chrome.tabs.move(tabId, { windowId: session.windowId, index: -1 }) rejects — e.g. the tab was closed during recovery, the target window no longer exists, the extension lacks the 'tabs' permission, or the tab is of a type that cannot be moved (pinned/protected windows).","commonSituations":"Target window closed by the user or another extension between drift detection and the move; a tab-pinning extension holds the tab; Chrome refuses to move tabs into windows with different profiles; the tab id became stale because navigation replaced it.","solutions":["Retry the command; a fresh navigation usually re-anchors the tab correctly.","Verify the session window still exists (chrome.windows.get) and that no extension closed it; reopen the browser profile if windows were closed.","Disable competing tab-management extensions that close or pin windows during automation.","Check the extension has the 'tabs' (and 'debugger' where needed) permissions in extension/src/manifest."],"exampleFix":"// before: catch (moveErr) { console.warn(`[opencli] Failed to recover drifted tab: ${moveErr}`); }\n// after (user-side workaround): rerun with competing tab extensions disabled so the move succeeds","handlingStrategy":"try-catch","validationCode":"try { await chrome.windows.get(session.windowId); } catch { /* session window gone — recreate before moving tab */ }","typeGuard":"function canRecover(tab, session) {\n  return Boolean(tab && session?.windowId != null && tab.id != null);\n}","tryCatchPattern":"try {\n  await chrome.tabs.move(tabId, { windowId: session.windowId, index: -1 });\n} catch (moveErr) {\n  console.warn(`[opencli] Failed to recover drifted tab: ${moveErr}`);\n  // fallback: recreate the tab in the session window or rerun the command\n}","preventionTips":["Keep the session window open for the whole automation run.","Avoid extensions that close, pin, or relocate windows mid-run.","Rerun the command after any drift-recovery warning to re-anchor the tab."],"tags":["chrome-extension","tabs","recovery-failed"],"backgroundTag":"tab-move-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}