grafana/k6 · warning

removing downloads path: %w

Error message

removing downloads path: %w

What it means

During BrowserContext.cleanup (browser_context.go:112), k6 runs os.RemoveAll on the downloads directory it created for the context. If the removal fails — permission loss, files held open, failing mount — the error is wrapped as 'removing downloads path: %w'. The context itself is still considered closed; the practical impact is a leaked temp directory.

Source

Thrown at internal/js/modules/k6/browser/common/browser_context.go:112

func (b *BrowserContext) setDownloadsPath(path string) error {
	path = strings.TrimSpace(path)
	if path != "" {
		b.DownloadsPath = path
		return nil
	}
	dir, err := os.MkdirTemp(os.TempDir(), artifactsDirectory+"*") //nolint:forbidigo
	if err != nil {
		return fmt.Errorf("creating temporary directory for downloads: %w", err)
	}
	b.DownloadsPath = dir

	return nil
}

// cleanup cleans up the resources associated with the browser context.
func (b *BrowserContext) cleanup() error {
	if err := os.RemoveAll(b.DownloadsPath); err != nil { //nolint:forbidigo
		return fmt.Errorf("removing downloads path: %w", err)
	}
	b.DownloadsPath = ""

	return nil
}

// NewBrowserContext creates a new browser context.
func NewBrowserContext(
	ctx context.Context, browser *Browser, id cdp.BrowserContextID, opts *BrowserContextOptions, logger *log.Logger,
) (*BrowserContext, error) {
	// set the default options if none provided.
	if opts == nil {
		opts = DefaultBrowserContextOptions()
	}
	// Always use the [Browser]'s user agent if it's not set by the user.
	// Setting this forces [FrameSession] to set Chromium's user agent.
	if strings.TrimSpace(opts.UserAgent) == "" {
		opts.UserAgent = browser.UserAgent()

View on GitHub (pinned to 93accf6570)

Solutions

  1. Check the wrapped syscall error (EACCES/EBUSY) and fix permissions or close file handles before context close
  2. Clean leftover artifacts-* dirs under /tmp between runs
  3. Use an explicit downloadsPath on a volume you manage so cleanup is deterministic
Defensive patterns

Strategy: try-catch

Validate before calling

// close file handles and stop writers before ending the context
// use an explicit downloadsPath you control to make cleanup predictable

Try / catch

try {
  await ctx.close()
} catch (e) {
  if (/removing downloads path/.test(String(e))) {
    // context is closed; schedule manual cleanup of the leaked artifacts-* dir
  } else throw e
}

Prevention

When it happens

Trigger: Files in the download directory still held/locked by another process; directory on NFS/FUSE returning errors; the k6 process losing permission (uid change, SELinux); path already altered by concurrent cleanup.

Common situations: Downloaded files still open when the context closes; exotic mounts in CI; leftover /tmp/artifacts-* dirs accumulating after repeated failures.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/becdedfaf2e3bfb2. Report an issue: GitHub.