different-ai/openwork · error · Error

Tab order must not contain duplicate tabs.

Error message

Tab order must not contain duplicate tabs.

What it means

reorderBrowserTabs rejects order arrays containing the same tab id twice, detected via Set size vs array length. Duplicates would make the permutation ambiguous, so the request is refused.

Source

Thrown at apps/desktop/electron/browser-panel.mjs:685

    hideBrowserView();
    browserTabs.clear();
    browserTabOrder = [];
    activeBrowserTabId = null;
    for (const tab of tabsToClose) {
      try { tab.view.webContents.close(); } catch { /* already destroyed */ }
    }
    sendToRenderer("openwork:browser:panel-closed");
    sendBrowserState();
    return closedTabIds;
  }

  function reorderBrowserTabs(tabIds) {
    const nextOrder = Array.isArray(tabIds) ? tabIds.map(String) : [];
    if (nextOrder.length !== browserTabOrder.length) {
      throw new Error("Tab order must include every open tab.");
    }
    if (new Set(nextOrder).size !== nextOrder.length) {
      throw new Error("Tab order must not contain duplicate tabs.");
    }
    const current = new Set(browserTabOrder);
    if (nextOrder.some((tabId) => !current.has(tabId))) {
      throw new Error("Tab order contains an unknown tab.");
    }
    browserTabOrder = nextOrder;
    sendBrowserState();
    return listBrowserTabs();
  }

  function sendBrowserState() {
    sendToRenderer("openwork:browser:state", browserStatePayload());
  }

  /**
   * Attach the browser view to the main window.
   * @param {object} bounds — { x, y, width, height }
   * @param {object} [opts]

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Deduplicate the payload (Array.from(new Set(ids))) before sending, after fixing the source bug
  2. Fix the drag handler to remove the item from its old position before inserting at the target
  3. Validate the constructed order client-side (unique ids, same length as open tabs) before the call

Example fix

// before
reorderBrowserTabs([...ids, draggedId]);
// after
const next = Array.from(new Set([draggedId, ...ids]));
reorderBrowserTabs(next);
Defensive patterns

Strategy: validation

Validate before calling

function hasNoDuplicates(ids) { return new Set(ids.map(String)).size === ids.length; }
if (!hasNoDuplicates(order)) throw new Error('reorder payload contains duplicate tab ids');

Type guard

function isUniqueStringArray(v) { return Array.isArray(v) && new Set(v.map(String)).size === v.length; }

Try / catch

try {
  reorderBrowserTabs(order);
} catch (e) {
  if (e.message === 'Tab order must not contain duplicate tabs.') {
    reorderBrowserTabs(Array.from(new Set(order.map(String))));
  } else throw e;
}

Prevention

When it happens

Trigger: Calling reorder with an array where one tabId appears two or more times — typically from a buggy drag-and-drop handler concatenating arrays or failing to remove the dragged item before reinserting it.

Common situations: Drag-and-drop logic double-inserting the dragged tab; merging a moved-tab list with the full list without deduping; client state corruption after rapid reorder calls.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/48df83fa36f9b637. Report an issue: GitHub.