{"record":{"id":"204e89f495bf0868","repo":"different-ai/openwork","slug":"tab-order-contains-an-unknown-tab","errorCode":null,"errorMessage":"Tab order contains an unknown tab.","messagePattern":"Tab order contains an unknown tab\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/browser-panel.mjs","lineNumber":689,"sourceCode":"    for (const tab of tabsToClose) {\n      try { tab.view.webContents.close(); } catch { /* already destroyed */ }\n    }\n    sendToRenderer(\"openwork:browser:panel-closed\");\n    sendBrowserState();\n    return closedTabIds;\n  }\n\n  function reorderBrowserTabs(tabIds) {\n    const nextOrder = Array.isArray(tabIds) ? tabIds.map(String) : [];\n    if (nextOrder.length !== browserTabOrder.length) {\n      throw new Error(\"Tab order must include every open tab.\");\n    }\n    if (new Set(nextOrder).size !== nextOrder.length) {\n      throw new Error(\"Tab order must not contain duplicate tabs.\");\n    }\n    const current = new Set(browserTabOrder);\n    if (nextOrder.some((tabId) => !current.has(tabId))) {\n      throw new Error(\"Tab order contains an unknown tab.\");\n    }\n    browserTabOrder = nextOrder;\n    sendBrowserState();\n    return listBrowserTabs();\n  }\n\n  function sendBrowserState() {\n    sendToRenderer(\"openwork:browser:state\", browserStatePayload());\n  }\n\n  /**\n   * Attach the browser view to the main window.\n   * @param {object} bounds — { x, y, width, height }\n   * @param {object} [opts]\n   * @param {boolean} [opts.preloadDefault=false] - load default URL if the view has no URL\n   * @param {boolean} [opts.ensureTab=false] - create a blank tab if needed\n   */\n  function attachBrowserView(bounds, { preloadDefault = false, ensureTab = false } = {}) {","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/desktop/electron/browser-panel.mjs#L671-L707","documentation":"reorderBrowserTabs checks every proposed id against the current open-tab set and throws if any id is not currently open. The order array was the right length with unique entries but referenced a tab that no longer (or never did) exist.","triggerScenarios":"Reordering with an id from a tab closed between snapshot and call; fabricated/corrupt ids; ids carried over from a previous panel session.","commonSituations":"Race where a tab closes while the user reorders; stale client state after a crash-restore; automation scripts hardcoding tab ids.","solutions":["Re-fetch listBrowserTabs() and rebuild the order from live ids","Intersect the proposed order with currently open tabs, appending any missing open tabs","Handle tab-close events to purge stale ids from client state before reordering"],"exampleFix":"// before\nreorderBrowserTabs(cachedOrder);\n// after\nconst open = new Set(listBrowserTabs().map(t => t.tabId));\nreorderBrowserTabs([...cachedOrder.filter(id => open.has(id)), ...[...open].filter(id => !cachedOrder.includes(id))]);","handlingStrategy":"validation","validationCode":"function orderUsesOpenTabs(ids) {\n  const open = new Set(listBrowserTabs().map(t => String(t.tabId)));\n  return ids.map(String).every(id => open.has(id));\n}\nif (!orderUsesOpenTabs(order)) order = order.filter(id => orderUsesOpenTabs([id]));","typeGuard":"function areKnownTabIds(ids, open) {\n  const known = new Set(open.map(t => String(t.tabId)));\n  return ids.map(String).every(id => known.has(id));\n}","tryCatchPattern":"try {\n  reorderBrowserTabs(order);\n} catch (e) {\n  if (e.message === 'Tab order contains an unknown tab.') {\n    const open = listBrowserTabs().map(t => t.tabId);\n    reorderBrowserTabs(order.filter(id => open.includes(id)).concat(open.filter(id => !order.includes(id))));\n  } else throw e;\n}","preventionTips":["Purge closed tab ids from client state on close events","Snapshot tab ids immediately before reordering to narrow race windows","Never hardcode tab ids in scripts; always read current state","Handle async tab closes with a reconcile-then-retry pattern"],"tags":["validation","browser-tabs","stale-reference"],"backgroundTag":"unknown-tab-id","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}