Skip to content

[Bug]: routeFromHAR fails with "Specified archive does not have a .har file" when inner zip entry has uppercase .HAR extension #43669

Closed

Description

Version

1.50.0 (and main)

Steps to reproduce

  1. Create a zip archive archive.har.zip containing a valid HAR file, but named with uppercase extension (e.g. Recording.HAR or session.Har from DevTools / external tools).
  2. Call context.routeFromHAR on the zip file:
import { test, expect } from '@playwright/test';

test('repro uppercase har entry in zip', async ({ context }) => {
  // archive.har.zip holds a valid HAR entry named "Recording.HAR"
  await context.routeFromHAR('archive.har.zip');
});

### Expected behavior

The HAR archive should replay successfully regardless of inner entry casing, matching the case-insensitive .zip extension handling introduced in #43550.

### Actual behavior

Fails with:
Error: Specified archive does not have a .har file

This occurs because localUtils.ts uses entryNames.find(e => e.endsWith('.har')) case-sensitively, so valid archives with entries like Recording.HAR or session.Har are rejected.

### Additional context

This is the inner-entry counterpart to #43550 (`fix(har): recognize .zip extensions regardless of case`). While #43550 made the archive file extension case-insensitive, the entry name checks inside `packages/playwright-core/src/server/localUtils.ts` remained case-sensitive:

```diff
diff --git a/packages/playwright-core/src/server/localUtils.ts b/packages/playwright-core/src/server/localUtils.ts
index df62972b2..2be37ea7a 100644
--- a/packages/playwright-core/src/server/localUtils.ts
+++ b/packages/playwright-core/src/server/localUtils.ts
@@ -153,7 +153,7 @@ export async function harOpen(progress: Progress, harBackends: Map<string, HarBa
   const zipFile = new ZipFile(params.file);
   try {
     const entryNames = await progress.race(zipFile.entries());
-    const harEntryName = entryNames.find(e => e.endsWith('.har'));
+    const harEntryName = entryNames.find(e => /\.har$/i.test(e));
     if (!harEntryName)
       return { error: 'Specified archive does not have a .har file' };
     const har = await progress.race(zipFile.read(harEntryName));
@@ -193,7 +193,7 @@ export async function harUnzip(progress: Progress, params: channels.LocalUtilsHa
   try {
     for (const entry of await progress.race(zipFile.entries())) {
       const buffer = await progress.race(zipFile.read(entry));
-      if (entry === 'har.har') {
+      if (/^har\.har$/i.test(entry)) {
         await progress.race(fs.promises.writeFile(params.harFile, buffer));
       } else {
         if (!resourcesDirCreated) {

i already have this patch and a passing test (HA-114 in tests/library/browsercontext-har.spec.ts) verified locally against the full test suite (101 HAR tests passing).

If community PRs are welcome for this, i would be very happy to submit the PR! Alternatively, if the core team / triage bot prefers handling it directly like in #43550, please feel free to pick up the diff above.

Environment

System:
OS: macOS 15.5
CPU: (10) arm64 Apple M1 Max
Binaries:
Node: 22.22.3
npm: 10.9.8
npmPackages:
playwright: latest

Activity

  1. github-actions commented on Oct 28, 2026

    @github-actions
  2. github-actions commented on Oct 28, 2026

    @github-actions
    Contributor

    Hi, I'm the Playwright bot and I reproduced this on Linux.

    Reproduced on 1.65.0-next (1b9b602724484df3ebc41aba77824fdfaba861f6) in Chromium, Firefox, and WebKit. The archive opens, but harOpen checks the inner .har extension case-sensitively. A verified fix makes that check case-insensitive while preserving the original entry name when reading the file.

    Reproduction and verification

    The regression extends the existing HA-085 should round-trip har.zip test: record and replay the lowercase HAR, then repack the same archive with har.har renamed to Recording.HAR, retaining all response-body files, and replay it again. It checks both the HTML body and the stylesheet.

    Before the fix, the second context.routeFromHAR() call failed with Specified archive does not have a .har file on all three browsers. With the fix, the HAR suites passed.

    • Platform: Linux, headless.
    • Bundled browsers: Chromium 157.0.8103.15, Firefox 158.0, WebKit 27.2.
    • Before fix: npm run test -- tests/library/browsercontext-har.spec.ts --grep HA-085 --workers=3 --retries=0 --reporter=line — 3 failures with the reported error.
    • After fix: npm run test -- tests/library/browsercontext-har.spec.ts tests/library/har.spec.ts tests/library/har-websocket.spec.ts --workers=3 --retries=0 --reporter=dot — 336 passed, 6 skipped.
    • npm run build and npm run flint passed.

    The proposed fix does not change harUnzip: that internal extraction path receives Playwright-generated archives, whose HAR entry is always named har.har.

    Draft fix: #43725

    Triaged on Linux by the Playwright bot - agent run

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions