{"record":{"id":"ddc5beec32ab38ac","repo":"browsh-org/browsh","slug":"a-headless-firefox-is-already-running","errorCode":null,"errorMessage":"A headless Firefox is already running","messagePattern":"A headless Firefox is already running","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"interfacer/src/browsh/firefox.go","lineNumber":102,"sourceCode":"\t\tShutdown(err)\n\t}\n\tif err := firefoxProcess.Start(); err != nil {\n\t\tShutdown(err)\n\t}\n\tin := bufio.NewScanner(stdout)\n\tfor in.Scan() {\n\t\tslog.Info(\"FF-CONSOLE\", \"stdout\", in.Text())\n\t}\n}\n\nfunc checkIfFirefoxIsAlreadyRunning() {\n\tif runtime.GOOS == \"windows\" {\n\t\treturn\n\t}\n\tprocesses := Shell(\"ps aux\")\n\tr, _ := regexp.Compile(\"firefox.*--headless\")\n\tif r.MatchString(processes) {\n\t\tShutdown(errors.New(\"A headless Firefox is already running\"))\n\t}\n}\n\nfunc ensureFirefoxBinary() string {\n\tpath := viper.GetString(\"firefox.path\")\n\tif path == \"firefox\" {\n\t\tswitch runtime.GOOS {\n\t\tcase \"windows\":\n\t\t\tpath = getFirefoxPath()\n\t\tcase \"darwin\":\n\t\t\tpath = \"/Applications/Firefox.app/Contents/MacOS/firefox\"\n\t\tdefault:\n\t\t\tpath = getFirefoxPath()\n\t\t}\n\t}\n\tif _, err := os.Stat(path); err != nil {\n\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\terr = errors.New(\"Firefox binary not found: \" + path)","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/browsh-org/browsh/blob/499ef386d45cd1e2b5457dd04887c017f77b7e27/interfacer/src/browsh/firefox.go#L84-L120","documentation":"Browsh's interfacer refuses to start another headless Firefox when it detects an existing one. On non-Windows platforms `checkIfFirefoxIsAlreadyRunning` runs `ps aux` and matches any process line against the regex `firefox.*--headless`; a match means a headless instance (possibly a previous browsh run) is still alive, and starting a second one would conflict over the Web Extension connection and resources. The process calls `Shutdown`, terminating browsh.","triggerScenarios":"Calling StartFirefox (via `startHeadlessFirefox` or `startWERFirefox`) when `ps aux` output contains a line matching `firefox.*--headless` — e.g. a leftover headless Firefox from a crashed or still-running browsh session. Never triggered on Windows (the check returns early).","commonSituations":"Previous browsh run didn't clean up its Firefox child process; a systemd/CI job left Firefox running; a script that starts browsh in a loop without killing the old instance; running two browsh instances concurrently in the same container.","solutions":["Find and kill the existing headless Firefox: `pkill -f 'firefox.*--headless'`, then retry.","Run `ps aux | grep firefox` to confirm it is safe to kill before killing it.","Avoid running multiple browsh instances simultaneously; serialize browsh invocations in scripts/CI.","If browsh crashed and left orphans, fix cleanup (trap signals, use process groups) so Firefox is terminated with browsh."],"exampleFix":"// before (shell, failing)\nbrowsh http://example.com  # Error: A headless Firefox is already running\n// after\npkill -f 'firefox.*--headless' || true\nbrowsh http://example.com","handlingStrategy":"validation","validationCode":"const { execSync } = require('child_process');\nconst running = execSync('ps aux').toString().match(/firefox.*--headless/);\nif (running) throw new Error('Kill existing headless Firefox before starting browsh');","typeGuard":null,"tryCatchPattern":"try {\n  startBrowsh();\n} catch (e) {\n  if (/headless Firefox is already running/.test(e.message)) {\n    execSync(\"pkill -f 'firefox.*--headless'\");\n    startBrowsh();\n  } else { throw e; }\n}","preventionTips":["pkill -f 'firefox.*--headless' before launching browsh in scripts/CI.","Never run multiple browsh instances concurrently in the same environment.","Use signal traps so browsh and its Firefox child die together on exit.","When browsh won't start, inspect `ps aux | grep firefox` first."],"tags":["process","firefox","startup"],"backgroundTag":"headless-firefox-already-running","analyzedSha":"499ef386d45cd1e2b5457dd04887c017f77b7e27","analyzedAt":"2026-09-02T19:05:32.228Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}