microsoft/playwright · warning · Error
Frame does not yet have the execution context
Error message
Frame does not yet have the execution context
What it means
nonStallingEvaluateInExistingContext throws when the requested world's context is not yet present in the frame's context data. Unlike the main-context variant it covers any world (main or utility) and fires when that world has not been initialized.
Solutions
- Use context(world) which awaits the world's contextPromise instead of the non-stalling variant.
- Wait for the frame to reach a stable lifecycle state.
- Skip the operation if the frame is being detached.
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
// Prefer the awaited context accessor const ctx = await frame.context(world);
Type guard
function hasContext(frame: any, world: string): boolean {
return !!frame._contextData?.get(world)?.context;
} Try / catch
null
Prevention
- Do not call the nonStalling* internal APIs from user code.
- Guard new-frame operations behind a load-state wait.
When it happens
Trigger: Calling nonStallingEvaluateInExistingContext for a world whose context data has no .context yet - common on freshly attached frames, frames whose utility world is not ready, or frames being torn down.
Common situations: Same as 311 plus utility-world scenarios: internal helper evaluations that run before the utility world is set up; operations queued during frame detachment.
Related errors
- Frame does not yet have a main execution context
- Can not *-capture inside a frame-piercing selector, while…
- Can not capture the selector before diving into the frame…
- Cannot serialize result: object reference chain is too long.
- Frame has been detached.
AI-assisted analysis of microsoft/playwright@f1d33b5029 (2026-08-12).
Data as JSON: /api/errors/ae85b61e138dae29.
Report an issue: GitHub.
Appendix: source
Thrown at packages/playwright-core/src/server/frames.ts:633
} finally {
this._raceAgainstEvaluationStallingEventsPromises.delete(promise);
}
}
nonStallingRawEvaluateInExistingMainContext(expression: string): Promise<any> {
return this.raceAgainstEvaluationStallingEvents(() => {
const context = this.existingContext('main');
if (!context)
throw new Error('Frame does not yet have a main execution context');
return context.rawEvaluateJSON(expression);
});
}
nonStallingEvaluateInExistingContext(expression: string, world: types.World): Promise<any> {
return this.raceAgainstEvaluationStallingEvents(() => {
const context = this._contextData.get(world)?.context;
if (!context)
throw new Error('Frame does not yet have the execution context');
return context.evaluateExpression(expression, { isFunction: false });
});
}
_recalculateNetworkIdle(frameThatAllowsRemovingNetworkIdle?: Frame) {
let isNetworkIdle = this._firedNetworkIdleSelf;
for (const child of this._childFrames) {
child._recalculateNetworkIdle(frameThatAllowsRemovingNetworkIdle);
// We require networkidle event to be fired in the whole frame subtree, and then consider it done.
if (!child._firedLifecycleEvents.has('networkidle'))
isNetworkIdle = false;
}
if (isNetworkIdle && !this._firedLifecycleEvents.has('networkidle')) {
this._firedLifecycleEvents.add('networkidle');
this.emit(Frame.Events.AddLifecycle, 'networkidle');
if (this === this._page.mainFrame() && this._url !== 'about:blank')
this.apiLog(` "networkidle" event fired`);
}View on GitHub (pinned to f1d33b5029)