cloudflare / cloudflare/cloudflare-os

Browser exports time out during Wrangler's cold Chrome installation

Open
#393 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
9.9k
Forks
1.2k
Avg merge
1d 20h
Merged PRs (30d)
107

Description

## Description

When running the Workshop locally with `pnpm run-local`, a browser-rendered Gadget export can fail after 30 seconds while Wrangler is downloading or recovering its local Chrome installation. This was observed while downloading an export from a generated Sheets object.

Wrangler logs that it detected a corrupted Chrome cache, clears it, and starts downloading Chrome. The Workshop then throws `Browser export timed out.` even though the browser download continues to 100%.

## Reproduction

1. Ensure Wrangler does not have a complete cached Chrome installation (a cold cache or an interrupted/incomplete install reproduces the condition).
2. Run `pnpm run-local`.
3. Open a Gadget and request a browser-mode export such as HTML or PDF.
4. Observe Chrome downloading.
5. After 30 seconds, the export fails with `Browser export timed out.` from `renderGadgetInBrowser()`.

The repository’s focused test can reproduce the same timing path by leaving `launch()` pending and advancing the clock 30,000 ms:

- `packages/workshop-backend/__tests__/browser-export.test.ts` — “disposes the Gadget and closes a browser that launches after the deadline”

## Expected behavior

A cold local Chrome download/startup should be allowed to finish. The normal 30-second generation and delivery limit should apply after the browser is available.

## Actual behavior

`renderGadgetInBrowser()` creates the shared export deadline before calling `launch()`:

- `packages/workshop-backend/src/browser-export.ts:169-174`
- `packages/workshop-backend/src/export-limits.ts:2` defines `MAX_EXPORT_DURATION_MS = 30_000`

As a result, browser provisioning, rendering, and stream delivery all share the same 30-second budget. Wrangler/Miniflare separately allows a substantially longer browser startup window to accommodate on-demand browser installation, but the Workshop deadline wins first.

The continued “Downloading browser...” output after the exception is consistent with the existing comment in `browser-export.ts`: a timed-out launch cannot be cancelled.

## Additional evidence

The affected cache contained a valid 160,132,145-byte Chrome ZIP but an incomplete extracted directory with no Chrome executable. Extracting that ZIP separately produced a working Chrome for Testing 126.0.6478.182 installation, confirming that the recovery path—not the downloaded archive contents—was colliding with the short application deadline.

The focused browser-export timeout test and the standard output-format test both pass. The latter confirms that the shipped Workspace Sheets CSV exporter is server-mode; therefore, if CSV itself enters this browser path, that would indicate an additional format-resolution issue. The supplied stack trace conclusively shows that this particular request selected the browser-rendered path in `OverseerImpl.exportGadget()`.

## Suggested fix

Give `launch()` a separate, longer browser-startup deadline, then begin the existing 30-second generation/delivery deadline only after launch succeeds. This preserves bounded cleanup and export execution while allowing Wrangler’s cold local browser provisioning to complete.

Contributor guide

Open the contributing guide

Research direction

Start in packages/workshop-backend/src/browser-export.ts around lines 169-174 and review packages/workshop-backend/src/export-limits.ts. Run the focused test in packages/workshop-backend/__tests__/browser-export.test.ts, especially “disposes the Gadget and closes a browser that launches after the deadline,” then trace the launch and deadline lifecycle. Done means cold browser startup can finish before the generation and delivery limit begins, with cleanup and timeout coverage still passing.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.