Skip to content

[Bug]: APIRequestContext errors lose structured fields (err.code is undefined) after cross-process serialization #42532

Description

Steps to reproduce

Errors thrown by the APIRequestContext (page.request, request.newContext(), request fixture) lose all structured node error fields. Run:

// repro.mjs — npx playwright@latest repro.mjs (or via a test)
import { request } from '@playwright/test'

const context = await request.newContext()
try {
  // Port 1 refuses connections: the underlying node error has `code: 'ECONNREFUSED'`.
  await context.post('http://127.0.0.1:1/', { data: {} })
} catch (err) {
  console.log('name      :', err.name)
  console.log('code      :', err.code)
  console.log('own props :', Object.getOwnPropertyNames(err))
  console.log('message   :', JSON.stringify(err.message.split('\n', 1)[0]))
}
await context.dispose()

Expected

The thrown error preserves the underlying node error's structured fields (at minimum err.code), so callers can distinguish network error kinds (ECONNRESET, ECONNREFUSED, EPIPE, …) programmatically. Plain node:http exposes err.code for exactly the same failure.

Actual

name      : Error
code      : undefined
own props : [ "stack", "message", "log", "name" ]
message   : "apiRequestContext.post: connect ECONNREFUSED 127.0.0.1:1"

The error is rebuilt client-side from the driver payload, so only stack / message / log / name survive; the node code is dropped. The only remaining signal is the message first line (apiRequestContext.post: connect ECONNREFUSED host:port, … read ECONNRESET, … socket hang up), which callers have to parse as free text — a Request was cancelled for a URL containing "econnreset" anywhere in its call log would defeat such string matching.

Use case

Transient network errors (localhost flakiness under load) are commonly retried in test setup helpers. With err.code available this is a precise code === 'ECONNRESET' check; today it requires fragile message-text matching. #30978 added built-in maxRetries for ECONNRESET specifically, but any user-side retry / error classification logic still has no structured signal to work with.

Environment: Playwright 1.62.1, Windows x64, Node 26.

Activity

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

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions