projectdiscovery/katana · error

could not create temporary chrome data directory

Error message

could not create temporary chrome data directory

What it means

Thrown when os.MkdirTemp fails to create a temporary Chrome profile directory inside ChromeUser.HomeDir. Katana needs a writable per-run data dir to launch headless Chrome; without it the page cannot start. The wrap preserves the underlying OS error (e.g. permission denied, no such directory).

Source

Thrown at pkg/engine/headless/browser/browser.go:386

	return err
}

func (l *Launcher) createBrowserPageFunc() (*BrowserPage, error) {
	// When using ChromeWSUrl, we don't need temp directories
	// since we're connecting to an existing browser
	var tempDir string
	shouldCleanupTempDir := false

	if l.opts.ChromeWSUrl == "" {
		if l.opts.UserDataDir != "" {
			// Use user-provided data directory (preserve sessions/cookies)
			tempDir = l.opts.UserDataDir
			shouldCleanupTempDir = false
		} else if l.opts.ChromeUser != nil {
			var err error
			tempDir, err = os.MkdirTemp(l.opts.ChromeUser.HomeDir, "chrome-data-*")
			if err != nil {
				return nil, errors.Wrap(err, "could not create temporary chrome data directory")
			}

			uid, err := strconv.Atoi(l.opts.ChromeUser.Uid)
			if err != nil {
				_ = os.RemoveAll(tempDir)
				return nil, errors.Wrap(err, "invalid user ID")
			}
			gid, err := strconv.Atoi(l.opts.ChromeUser.Gid)
			if err != nil {
				_ = os.RemoveAll(tempDir)
				return nil, errors.Wrap(err, "invalid group ID")
			}
			if err := os.Chown(tempDir, uid, gid); err != nil {
				_ = os.RemoveAll(tempDir)
				return nil, errors.Wrap(err, "could not change ownership of chrome data directory")
			}
			shouldCleanupTempDir = true
		} else {

View on GitHub (pinned to e3e742739c)

Solutions

  1. Verify ChromeUser.HomeDir exists and is writable by the process user (ls -ld; touch a test file).
  2. If running in Docker, ensure the home directory is created (useradd -m) or mount a writable volume there.
  3. Run the process as the ChromeUser or grant write permission on HomeDir (chown/chmod, securityContext).
  4. Check disk space (df -h) and that the filesystem is not mounted read-only.
  5. If a dedicated chrome user is unnecessary, leave ChromeUser nil so katana uses the default system temp dir.

Example fix

// before
u, _ := user.Lookup("chrome")
opts.ChromeUser = u // home may not exist
// after
if _, err := os.Stat(u.HomeDir); err != nil {
    os.MkdirAll(u.HomeDir, 0o700)
    os.Chown(u.HomeDir, mustAtoi(u.Uid), mustAtoi(u.Gid))
}
opts.ChromeUser = u
Defensive patterns

Strategy: validation

Validate before calling

if opts.ChromeUser != nil {
    if _, err := os.Stat(opts.ChromeUser.HomeDir); err != nil {
        os.MkdirAll(opts.ChromeUser.HomeDir, 0o700) // or fall back to ChromeUser=nil
    }
}

Type guard

func usableDir(p string) bool {
    fi, err := os.Stat(p)
    return err == nil && fi.IsDir()
}

Try / catch

page, err := l.createBrowserPageFunc(...)
if err != nil && strings.Contains(err.Error(), "temporary chrome data directory") {
    l.opts.ChromeUser = nil // fall back to default temp dir
    page, err = l.createBrowserPageFunc(...)
}

Prevention

When it happens

Trigger: LauncherOptions.ChromeUser is set (non-nil) and os.MkdirTemp(l.opts.ChromeUser.HomeDir, "chrome-data-*") returns an error — HomeDir does not exist, is not writable by the current process, or the filesystem is full/read-only.

Common situations: Running katana as a different user than the owner of ChromeUser.HomeDir; container images where the chrome user's home was never created; read-only root filesystem; disk quota exhausted; account missing on the host so user.Lookup-derived HomeDir is invalid.

Related errors


AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03). Data as JSON: /api/errors/623884747499b762. Report an issue: GitHub.