Skip to content

fix(extension): don't abort hub tasks when configure precedes execute - #618

Open
apakkhalin-sudo wants to merge 1 commit into
alibaba:mainfrom
apakkhalin-sudo:fix/hub-configure-dispose-race
Open

fix(extension): don't abort hub tasks when configure precedes execute#618
apakkhalin-sudo wants to merge 1 commit into
alibaba:mainfrom
apakkhalin-sudo:fix/hub-configure-dispose-race

Conversation

@apakkhalin-sudo

Copy link
Copy Markdown

Fixes #570

Problem

Every task sent through the MCP server fails instantly with "Task aborted" whenever any of LLM_BASE_URL / LLM_API_KEY / LLM_MODEL_NAME is set — even when those values are identical to the extension's saved settings. The extension popup works fine, and the hub makes zero network requests before failing.

Root cause

packages/mcp attaches a config object to every execute message when LLM env vars are set. In the hub, useHubWs.onExecute then does:

if (incomingConfig) {
  await configure({ ...config, ...incomingConfig } as ExtConfig)
}
const result = await execute(task)

configure() calls setConfig() in useAgent, which re-renders and re-runs the useEffect([config]). That effect's cleanup disposes the current agent and installs a new one — but execute() resolves agentRef before React commits the new agent, so the task starts (or is about to start) on the agent being disposed. dispose() fires its AbortController, and PageAgentCore returns the literal "Task aborted".

Observable in the hub tab's console on every MCP run: initDisposing PageAgent...dispose.

Fix (in useAgent.configure())

  1. Value-equal config → skip the rebuild. If the merged config equals the current one (the common MCP case, since the env config usually mirrors saved settings), don't setConfig at all — no re-render, no dispose. Storage writes still happen.
  2. Changed config → await the rebuild. configure() now resolves only after the [config] effect has installed the new agent, so callers never execute() on an agent whose dispose is already scheduled.

Verification

  • npm run typecheck, npm test (17/17), npm run lint, npm run build:ext all pass.
  • Runtime-verified the equivalent behavior end-to-end: with config no longer triggering a rebuild before execute, MCP execute_task completes successfully through hub → extension → LLM → page (previously 100% instant abort).

🤖 Generated with Claude Code

When the hub receives an execute message with a config payload, onExecute
awaits configure() and then calls execute(). configure()'s setConfig
re-renders useAgent, and the [config] effect cleanup disposes the current
agent — the very agent the caller is about to run (execute still resolves
agentRef to it). Its AbortController fires and every MCP task instantly
fails with 'Task aborted' (alibaba#570).

Two changes in useAgent.configure():
- Skip the agent rebuild entirely when the merged config is value-equal
  to the current one (the common MCP case: env config matches saved
  settings). Storage writes still happen.
- When config genuinely changed, resolve configure()'s promise only
  after the [config] effect has installed the new agent, so callers
  execute on the new agent instead of the disposed one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Instant "Task aborted" error when executing tasks via MCP due to React re-render & PageAgent disposal

2 participants