fix(browserbase): disable Stagehand hosted API to unblock connect#3230
Merged
Conversation
"Unknown error: 400" on Connect came from Stagehand's hosted API (POST /sessions/start) — a separate upstream from the premature-close fix. We create and own the Browserbase session ourselves and only need CDP navigation plus local inference, so the hosted-API round-trip is both unnecessary and the single point of failure for connect, login-check, and evidence runs (all route through createStagehand). Set disableAPI:true so Stagehand skips /sessions/start: the session still resumes over CDP, and extract/act/agent run locally against ANTHROPIC_API_KEY (verified: apiClient is only built inside the !disableAPI guard, and extract/agent fall back to local handlers when it is null). Also forward Stagehand's own error logs into the NestJS logger, because it strips upstream error bodies from its throws — so a future failure surfaces the real reason instead of "Unknown error: 400". Also fix the Trigger.dev maxDuration units for the scheduled runner and orchestrator: they were 1000*60*N (~166h / ~500h), so the intended 10/30-minute safety abort never tripped. maxDuration is in SECONDS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013zSwXMqVNvWLJBZEot9x12
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
🎉 This PR is included in version 3.87.2 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Browser Automations won't connect — clicking Connect fails with "Unknown error: 400". This is a different failure from the premature-close one fixed in #3225.
Root cause (verified)
/navigate→createStagehand()→stagehand.init(). WithdisableAPIleft at its default (false), Stagehand first calls its hosted managed API (POST https://api.stagehand.browserbase.com/v1/sessions/start) before connecting via CDP. That hosted call returns a400, and Stagehand throws"Unknown error: 400"after stripping the real reason out of the error (@browserbasehq/stagehand/.../v3/api.js:85-92).The key insight from a full audit of the feature: this feature needs nothing from the hosted API.
navigateToUrlonly doespage.goto()+sendCDP()— pure CDP, no LLM.checkLoginStatus(verify) and evidence runs useextract/agent({cua}), which run against local handlers + ourANTHROPIC_API_KEY.All three paths route through
createStagehand, so the hosted-API round-trip is the single point of failure for connect, login-verify, and scheduled evidence runs.Fix
Set
disableAPI: truein the Stagehand constructor. Verified against Stagehand v3.3.0 internals:apiClientis built only inside theif (!disableAPI && !experimental)block (v3.js:826/827), sodisableAPI:true→apiClientstays null → no/sessions/startcall → the 400 cannot occur.createBrowserbaseSessionruns unconditionally atv3.js:865).extract(v3.js:1110else-branch) and the CUAagent(v3.js:1594else-branch) fall back to local handlers whenapiClientis null;anthropic/claude-sonnet-4-6is inAVAILABLE_CUA_MODELSand resolves via@ai-sdk/anthropic(dep present).Also in this PR:
loggerconstructor hook). Stagehand strips upstream error bodies from its throws, so without this we're blind — this is why "Unknown error: 400" was opaque. Now the real reason lands in our logs.maxDurationunits for the scheduled runner + orchestrator: they were1000*60*N(≈166h / 500h), so the intended 10-/30-minute safety abort never tripped.maxDurationis in seconds (matches the convention inrun-device-sync.tsand its spec).The
init()retry from #3225 is kept — it still protects the CDP session-resume round-trip (a different upstream than the hosted API).Testing
createStagehandconstructs Stagehand withdisableAPI: true.Honest caveat
I verified in code that
extract/CUA fall back to local handlers, but I could not exercise a live Browserbase run. Connect/navigate is no-LLM and fully unblocked; please confirm one verify ("Check & Save") and one evidence run so we validate local-inference parity. If anything still fails, the new logger forwarding will now surface the real reason in the API logs instead of "Unknown error: 400".🤖 Generated with Claude Code
https://claude.ai/code/session_013zSwXMqVNvWLJBZEot9x12
Summary by cubic
Disable Stagehand’s hosted API to stop “Unknown error: 400” on Connect and run automations via CDP + local inference. Also fix task timeouts and forward Stagehand logs for clearer errors.
disableAPI: trueto Stagehand so it skipsPOST /sessions/start; CDP resume still works andextract/CUA run locally withANTHROPIC_API_KEY.loggerhook to surface real upstream reasons.init()retry for CDP session resume.maxDurationin seconds inrun-browser-automation(10m) andbrowser-automations-schedule(30m).Written for commit d74c644. Summary will update on new commits.