Troubleshooting
First steps
When something breaks, these two commands tell me most of what I need to know — they'll do the same for you:
# Full setup diagnostic — checks runtime, config, server, extension, plugins
opentabs doctor
# Server status — shows plugins, tab states, tool counts
opentabs statusIf the server isn't running, start it with opentabs start.
Extension not connecting
Symptom: The side panel shows "Disconnected" or opentabs status reports Extension: not connected.
- Server running? — Run
opentabs status. If the server is not running, start it withopentabs start. - Correct port? — Default is 9515. If using a custom port, make sure the extension is configured for the same one.
- Extension loaded? — Open
chrome://extensionsand verify OpenTabs is loaded and enabled. Click any error link for details. - Version mismatch? — Run
opentabs doctor. A mismatch between the installed extension and CLI version can cause failures. Restartopentabs startto auto-update the extension files, then reload the extension fromchrome://extensions. - Stale secret? — The extension reads the auth secret from
~/.opentabs/extension/auth.json(written by the server on startup). If the secret changed (e.g., after deletingauth.jsonor rotating the secret withopentabs config rotate-secret --confirm), restart the server withopentabs startto regenerate the file, then reload the extension fromchrome://extensions.
Extension reconnection delays
Symptom: After the server restarts, the extension takes several seconds to reconnect.
The extension uses exponential backoff: 1s, 2s, 4s, 8s, up to a 30-second cap. Backoff resets after a successful connection. To force an immediate reconnect, close and reopen the side panel.
Plugin showing as "unavailable"
Symptom: opentabs status shows a plugin as "unavailable". Tool calls to this plugin fail.
A plugin is unavailable when a matching tab exists but isReady() returns false — usually because the user is not logged in.
- Log in — Sign into the target web app. The extension re-probes
isReady()on navigation and tab events. - Refresh the tab — A fresh page load may be needed to detect the authentication state.
- Check isReady() logic — Verify it checks the right signal (localStorage token, DOM element, cookie). The probe has a 5-second timeout.
Plugin showing as "closed"
Symptom: opentabs status shows a plugin as "closed".
A plugin is closed when no Chrome tab matches its URL patterns.
- Open the target web app — Navigate to a URL matching the plugin's
urlPatterns. - Check URL patterns — Verify the
opentabs.urlPatternsfield inpackage.jsonuses valid Chrome match pattern syntax. - Multiple windows — The extension searches across all Chrome windows.
Tool dispatch timeout
Symptom: Tool calls fail after ~30 seconds.
| Cause | Solution |
|---|---|
| handle() takes too long | Add progress reporting to extend the timeout up to 5 minutes, or break long operations into multiple tool calls. |
| Tab unresponsive or crashed | Refresh the target tab. Check Chrome's task manager (Shift+Esc) for hung tabs. |
| Extension disconnected mid-call | The server detects this and returns an error. Reconnect the extension. |
| Network request in handle() stalled | Use the SDK's fetchFromPage() or fetchJSON() which have built-in 30-second timeouts. |
Use opentabs audit to see recent tool invocations with their durations and error details.
MCP client cannot connect
Symptom: Claude Code, Cursor, or another MCP client reports a connection or authentication error.
- Server running? —
opentabs statusorcurl http://127.0.0.1:9515/health - Correct URL — The endpoint is
http://127.0.0.1:9515/mcp(not/wsor/) - Auth token —
Authorization: Bearer <secret>must match thesecretin~/.opentabs/extension/auth.json. Get it with:bashopentabs config show --json --show-secret | jq -r .secret - Client config — For Claude Code, verify your MCP config has
"type": "streamable-http"and the correct URL and Authorization header - CORS — The server rejects requests with a browser
Originheader. Native MCP clients don't send Origin headers, so this should only affect browser-based testing.
Plugin changes not picked up
Symptom: After rebuilding a plugin, the server still serves old tool definitions.
The opentabs-plugin build command calls POST /reload automatically. If the server didn't pick up changes:
- Check the build — Verify that
dist/tools.jsonanddist/adapter.iife.jsexist in the plugin directory. - Check server logs —
opentabs logsshows recent server activity, including reload events. - Manual reload — Call the reload endpoint directly:
bash
curl -X POST http://127.0.0.1:9515/reload \ -H "Authorization: Bearer $(opentabs config show --json --show-secret | jq -r .secret)" - Verify via status —
opentabs statusshows the current plugin list and tool counts.
Extension changes not taking effect
Symptom: After modifying extension source and rebuilding, behavior is unchanged.
The Chrome extension does not auto-reload. After rebuilding:
- Open
chrome://extensions - Find the OpenTabs card and click the circular refresh icon
- Close and reopen the side panel
Side panel not updating
Symptom: The side panel shows stale data (wrong plugins, old tab states).
- Close and reopen — Right-click the extension icon and select "Open side panel"
- Reload the extension — From
chrome://extensions, click the refresh icon - Check server connection — If "Disconnected", see Extension not connecting
Build failures
| Error | Cause | Solution |
|---|---|---|
| TypeScript errors | Type mismatches or missing types | Run npm run type-check for details and fix the errors. |
| Zod schema serialization | .transform(), .pipe(), or .preprocess() in tool schemas | Move the logic to handle() — transforms can't be serialized to JSON Schema. See the Plugin Development guide for details. |
| Plugin name validation | Name has invalid characters or is reserved | Names must match ^[a-z0-9]+(-[a-z0-9]+)*$ (lowercase alphanumeric segments separated by single hyphens) and not be reserved (e.g., browser, extension). |
| Missing dependencies | @opentabs-dev/plugin-sdk not installed | Run npm install in the plugin directory. |
Diagnostic commands
| Command | What it does |
|---|---|
opentabs doctor | Full setup diagnostic — runtime, config, server, extension, plugins. |
opentabs status | Server health, plugin list, tab states, tool counts. |
opentabs audit | Recent tool invocation history with durations and errors. |
opentabs logs | Tail the MCP server log in real time. |
opentabs logs --plugin <name> | Show only logs from a specific plugin. |
opentabs config show | View current configuration (secret redacted). |
curl http://127.0.0.1:9515/health | Direct health check (no CLI needed). Without a Bearer token, returns only {"status": "ok"}. Pass -H "Authorization: Bearer <secret>" for the full payload including version and extensionConnected. |
Last Updated: 10 Mar, 2026