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).

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.

Appendix: 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)