{"record":{"id":"c859258e1d124a7f","repo":"microsoft/playwright","slug":"closed-c85925","errorCode":"closed","errorMessage":"Target page, context or browser has been closed","messagePattern":"Target page, context or browser has been closed","errorType":"exception","errorClass":"ProtocolError","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/webkit/wkConnection.ts","lineNumber":125,"sourceCode":"  private _disposed = false;\n  private readonly _rawSend: (message: any) => void;\n  private readonly _callbacks = new Map<number, { resolve: (o: any) => void, reject: (e: ProtocolError) => void, error: ProtocolError }>();\n  private _crashed: boolean = false;\n\n  constructor(connection: WKConnection, sessionId: string, rawSend: (message: any) => void) {\n    super();\n    this.setMaxListeners(0);\n    this.connection = connection;\n    this.sessionId = sessionId;\n    this._rawSend = rawSend;\n  }\n\n  async send<T extends keyof Protocol.CommandParameters>(\n    method: T,\n    params?: Protocol.CommandParameters[T]\n  ): Promise<Protocol.CommandReturnValues[T]> {\n    if (this._crashed || this._disposed || this.connection._browserDisconnectedLogs)\n      throw new ProtocolError(this._crashed ? 'crashed' : 'closed', undefined, this.connection._browserDisconnectedLogs);\n    const id = this.connection.nextMessageId();\n    const messageObj = { id, method, params };\n    this._rawSend(messageObj);\n    return new Promise<Protocol.CommandReturnValues[T]>((resolve, reject) => {\n      this._callbacks.set(id, { resolve, reject, error: new ProtocolError('error', method) });\n    });\n  }\n\n  sendMayFail<T extends keyof Protocol.CommandParameters>(method: T, params?: Protocol.CommandParameters[T]): Promise<Protocol.CommandReturnValues[T] | void> {\n    return this.send(method, params).catch(error => debugLogger.log('error', error));\n  }\n\n  markAsCrashed() {\n    this._crashed = true;\n  }\n\n  isDisposed(): boolean {\n    return this._disposed;","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/webkit/wkConnection.ts#L107-L143","documentation":"WKConnection.send() refuses to dispatch a protocol command when the session is in a terminal state: _crashed, _disposed, or the browser-level disconnected logs are set. It throws a ProtocolError with code 'closed' (or 'crashed'), carrying the browser-disconnect log payload so callers see why the target died.","triggerScenarios":"Any protocol send after page.close()/context.close()/browser.close() resolves, after a tab crash, or after the browser process exits. Commonly surfaces when an awaited operation races with teardown — e.g. an evaluate or screenshot completing after the test called close.","commonSituations":"Teardown races in afterEach hooks, operations on a page whose browser crashed, reusing a context after browser.disconnect(), or fire-and-forget code that runs past close(). On WebKit this is the unified 'target gone' signal.","solutions":["Ensure all page/context work is awaited before calling close(); structure teardown with Promise.all over in-flight ops first.","Guard sends with page.isClosed()/context.browser() checks, or wrap in try/catch and ignore 'closed' codes during teardown.","Investigate the actual crash: this error is a symptom; the disconnect logs in the error payload tell you why the target died."],"exampleFix":"// before\nawait page.click('#x');\nawait browser.close();\nawait page.title(); // throws closed\n\n// after\nconst title = await page.title();\nawait browser.close();","handlingStrategy":"try-catch","validationCode":"function canSend(page) { return !page.isClosed(); }\nif (canSend(page)) await page.title();","typeGuard":"null","tryCatchPattern":"try { await page.title(); }\ncatch (e) {\n  if (e.name === 'TargetClosedError' || /has been closed/.test(e.message)) return; // teardown race\n  throw e;\n}","preventionTips":["Await all in-flight page ops before close().","Guard sends with page.isClosed() during teardown."],"tags":["webkit","connection","closed","protocol","lifecycle"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}