d2lang/d2 · error

failed to install Playwright: %w

Error message

failed to install Playwright: %w

What it means

InitPlaywright wraps any error from playwright.Install() (which downloads the Chromium browser binary) with this message. The library calls it to ensure Chromium v149 is available before rendering non-SVG images. It indicates the browser download/install step failed, and the underlying cause is preserved via %w.

Source

Thrown at lib/png/png.go:87

	}
	page, err := context.NewPage()
	if err != nil {
		return Playwright{}, fmt.Errorf("failed to start new Playwright page: %w", err)
	}
	return Playwright{
		PW:      pw,
		Browser: browser,
		Page:    page,
	}, nil
}

func InitPlaywright() (Playwright, error) {
	err := playwright.Install(&playwright.RunOptions{
		Verbose:  false,
		Browsers: []string{"chromium"},
	})
	if err != nil {
		return Playwright{}, fmt.Errorf("failed to install Playwright: %w", err)
	}

	pw, err := playwright.Run()
	if err != nil {
		return Playwright{}, fmt.Errorf("failed to run Playwright: %w", err)
	}
	return startPlaywright(pw)
}

func InitPlaywrightWithPrompt() (Playwright, error) {
	if os.Getenv("CI") != "" {
		return InitPlaywright()
	}

	// Just try running first. This only works if drivers and browsers are already installed
	pw, err := playwright.Run()
	if err == nil {
		return startPlaywright(pw)

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Check network connectivity/proxy settings and retry; set HTTPS_PROXY if behind a corporate proxy
  2. Ensure the playwright browser cache directory is writable (check $HOME or PLAYWRIGHT_BROWSERS_PATH)
  3. Free disk space; Chromium download needs several hundred MB
  4. Pre-install the browser manually (playwright install chromium) and re-run
  5. Inspect the wrapped cause (%w) for the precise driver error

Example fix

// before
pw, err := InitPlaywright()
if err != nil { log.Fatal(err) }
// after
if err := os.Setenv("PLAYWRIGHT_BROWSERS_PATH", "/tmp/pw-browsers"); err != nil { log.Fatal(err) }
pw, err := InitPlaywright()
if err != nil { log.Fatalf("playwright init: %v (check network/disk)", err) }
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat(browserCacheDir()); err != nil && !hasNetwork() { t.Skip("no network for playwright install") }

Type guard

var pwe *playwright.Error // inspect wrapped cause
func installCause(err error) error { return errors.Unwrap(err) }

Try / catch

pw, err := InitPlaywright()
if err != nil {
    var dlErr error
    if errors.Is(err, context.DeadlineExceeded) { /* retry with proxy */ }
    _ = dlErr
    log.Printf("playwright install failed: %v", err)
    return fallbackSVGRendering()
}

Prevention

When it happens

Trigger: Calling InitPlaywright() or InitPlaywrightWithPrompt() when playwright.Install(&playwright.RunOptions{Browsers:["chromium"]}) fails: no network access, download interrupted, insufficient disk space, or unwritable playwright cache directory (e.g. ~/.cache/ms-playwright).

Common situations: CI containers with no internet egress or restricted DNS; corporate proxies blocking the CDN; read-only HOME in sandboxes/Docker; disk full; TLS interception breaking the download.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/952fcb7b32efeba4. Report an issue: GitHub.