{"record":{"id":"cf4d6267dabe1bb3","repo":"garrytan/gstack","slug":"buildfetchhandler-cfg-browsermanager-is-required","errorCode":null,"errorMessage":"buildFetchHandler: cfg.browserManager is required","messagePattern":"buildFetchHandler: cfg\\.browserManager is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"browse/src/server.ts","lineNumber":1474,"sourceCode":" * path calls this through start() with env-derived defaults and explicit\n * cfg.ownsTerminalAgent: true — externally-observable behavior is identical.\n *\n * Auth state lives ENTIRELY inside the factory closure: cfg.authToken is the\n * single source of truth for the bearer secret, factory-scoped validateAuth\n * closes over it, and factory-scoped shutdown closes the cfg-provided\n * browserManager. Module-level lifecycle singletons (LOCAL_LISTEN_PORT,\n * tunnelActive, inspector state) intentionally STAY at module scope; see\n * the v1.35.0.0 CHANGELOG entry for the architectural rationale.\n *\n * The returned ServerHandle is callable directly. Bun.serve is the caller's\n * responsibility — embedders may fd-pass; CLI uses Bun.serve normally.\n */\nexport function buildFetchHandler(cfg: ServerConfig): ServerHandle {\n  if (!cfg.authToken || cfg.authToken.length < 16) {\n    throw new Error('buildFetchHandler: cfg.authToken must be a non-empty string >= 16 chars');\n  }\n  if (!cfg.browserManager) {\n    throw new Error('buildFetchHandler: cfg.browserManager is required');\n  }\n\n  // Re-run init with cfg-provided values. ensureStateDir is idempotent\n  // (mkdir -p); initAuditLog is idempotent (sets a module string);\n  // initRegistry is idempotent for same-token, throws for different-token.\n  // Owning init here (instead of at module load) means cfg.authToken is the\n  // single source of truth for the registry root token.\n  ensureStateDir(cfg.config);\n  initAuditLog(cfg.config.auditLog);\n  initRegistry(cfg.authToken);\n\n  const { authToken, browserManager: cfgBrowserManager, startTime, beforeRoute, browsePort } = cfg;\n  // Strict opt-out: only explicit `false` flips the gate. Any other value\n  // (undefined, truthy non-bool from a JS caller bypassing TS, etc.) defaults\n  // to gstack-owns. Matches the \"default-true preserves CLI bit-for-bit\"\n  // premise even under malformed cfg.\n  const ownsTerminalAgent = cfg.ownsTerminalAgent === false ? false : true;\n","sourceCodeStart":1456,"sourceCodeEnd":1492,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/server.ts#L1456-L1492","documentation":"Error \"buildFetchHandler: cfg.browserManager is required\" thrown in garrytan/gstack.","triggerScenarios":"Thrown at browse/src/server.ts:1474 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}