fix(core): gracefully handle runtimes that omit AsyncLocalStorage.enterWith() (fixes #2055)#2062
Conversation
…erWith() (fixes browserbase#2055) Cloudflare Workers intentionally omit enterWith() from their AsyncLocalStorage implementation because it mutates context across the entire remaining async chain, which is unsafe under concurrent requests. Calling it throws immediately, crashing Stagehand during init() before any browser work begins. Wrap the enterWith() call in a try/catch so the init() path stays safe on any runtime. The returned FlowLoggerContext is still valid; callers that need ALS propagation use loggerContext.run() via runWithLogging() and withContext(), which are already runtime-safe. Adds a unit test that simulates the missing enterWith() and asserts that FlowLogger.init() completes without throwing and returns a valid context. Co-Authored-By: Octopus <liyuan851277048@icloud.com>
|
|
This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run. |
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant S as Stagehand / Caller
participant FL as FlowLogger
participant ALS as AsyncLocalStorage
participant Bus as Event Bus
Note over S, ALS: Initialization Flow (v3.ts)
S->>FL: init(sessionId, eventBus)
FL->>FL: Create FlowLoggerContext (ctx)
rect rgb(240, 240, 240)
Note right of FL: NEW: Guard against restricted runtimes
alt Runtime supports enterWith() (e.g. Node.js)
FL->>ALS: enterWith(ctx)
ALS-->>FL: Context globally set for current execution
else Runtime omits enterWith() (e.g. Cloudflare Workers)
FL->>ALS: enterWith(ctx)
ALS-->>FL: THROW: "not implemented"
FL->>FL: Catch and suppress error
end
end
FL-->>S: Return FlowLoggerContext
Note over S, ALS: Execution Flow (Post-Init)
S->>FL: runWithLogging(ctx, task)
Note right of FL: Explicit context path works even if enterWith() failed
FL->>ALS: run(ctx, task)
ALS->>Bus: Emit logging events
ALS-->>FL: Result
FL-->>S: Result
Fixes #2055
Problem
Since v3.2.0,
FlowLogger.init()callsAsyncLocalStorage.enterWith()to set the session-wide logging context. Cloudflare Workers intentionally omitsenterWith()from theirAsyncLocalStorageimplementation — calling it throwsasyncLocalStorage.enterWith() is not implemented, which crashes Stagehand immediately duringinit()before any browser interaction occurs.Solution
Wrap the
enterWith()call in atry/catch. If the runtime does not supportenterWith(), we fall through silently. TheFlowLoggerContextis still created and returned, so it can be stored by the caller (this.flowLoggerContextin v3.ts). All other ALS usage inside FlowLogger already usesloggerContext.run()(inrunWithLogging(),withContext(),logCdpEvent(), etc.), which is supported everywhere — so the logging pipeline continues to work through the explicit-context path on runtimes withoutenterWith().Testing
Added a unit test that simulates a runtime without
enterWith()(by temporarily settingAsyncLocalStorage.prototype.enterWith = undefined) and asserts thatFlowLogger.init()completes without throwing and returns a valid context.All existing flowlogger unit tests continue to pass.
Summary by cubic
Fixes #2055. Prevents crashes on runtimes that omit
AsyncLocalStorage.enterWith()(e.g., Cloudflare Workers) by safely initializingFlowLogger. Logging continues vialoggerContext.run()paths.enterWith()in try/catch inFlowLogger.init(); fall through when missing.enterWith()and verifies init succeeds and returns a validFlowLoggerContext.Written for commit 7211ad5. Summary will update on new commits. Review in cubic