{"record":{"id":"9d893582f2632c10","repo":"iOfficeAI/AionUi","slug":"webui-cannot-start-aioncore-is-not-running-glo","errorCode":null,"errorMessage":"[WebUI] Cannot start: aioncore is not running (globalThis.__backendPort unset)","messagePattern":"\\[WebUI\\] Cannot start: aioncore is not running \\(globalThis\\.__backendPort unset\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/desktop/src/process/bridge/webuiBridge.ts","lineNumber":55,"sourceCode":"    const json = (await res.json()) as { data?: AdminUsernameResult | null };\n    return json.data?.username ?? 'admin';\n  } catch {\n    return 'admin';\n  }\n}\n\n/**\n * On first Enable-WebUI click after a fresh install, the backend's users table\n * holds the seeded `system_default_user` row with an empty password_hash.\n * Probe /api/auth/status; if `needs_setup === true`, ask backend to generate\n * and persist a random password, then stash the plaintext for Settings to show\n * once. When the backend already has credentials (upgrade path handled by\n * ensureAdminUser, or a prior Enable-WebUI), this is a no-op.\n */\nasync function maybeSeedInitialPassword(): Promise<void> {\n  const port = getBackendPort();\n  if (!port) {\n    throw new Error('[WebUI] Cannot start: aioncore is not running (globalThis.__backendPort unset)');\n  }\n  const statusRes = await fetch(`http://127.0.0.1:${port}/api/auth/status`);\n  if (!statusRes.ok) {\n    throw new Error(`[WebUI] /api/auth/status returned ${statusRes.status}`);\n  }\n  const statusJson = (await statusRes.json()) as { needs_setup?: boolean; data?: { needs_setup?: boolean } };\n  const needsSetup = statusJson.needs_setup ?? statusJson.data?.needs_setup ?? false;\n  if (!needsSetup) {\n    setDesktopWebUIInitialPassword(undefined);\n    return;\n  }\n  const resetRes = await fetch(`http://127.0.0.1:${port}/api/webui/reset-password`, { method: 'POST' });\n  if (!resetRes.ok) {\n    throw new Error(`[WebUI] /api/webui/reset-password returned ${resetRes.status}`);\n  }\n  const resetJson = (await resetRes.json()) as { data?: { new_password?: string }; new_password?: string };\n  const newPassword = resetJson.data?.new_password ?? resetJson.new_password;\n  if (!newPassword) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/iOfficeAI/AionUi/blob/711aa0550ee183ea495dc33e2c05c7943b70a60a/packages/desktop/src/process/bridge/webuiBridge.ts#L37-L73","documentation":"Thrown by the WebUI seeding path when globalThis.__backendPort is unset, i.e. the aioncore backend process has not been started (or its port was never recorded) before the WebUI initialization ran.","triggerScenarios":"Calling maybeSeedInitialPassword (via initWebuiBridge) before backendManager.start() completed and set globalThis.__backendPort, or after the backend failed to start.","commonSituations":"Race between backend startup and WebUI bridge init, backend crash during startup, or running the WebUI bridge in a context where the backend was intentionally not spawned.","solutions":["Ensure backendManager.start() has resolved and set __backendPort before initWebuiBridge runs","Check the backend startup logs for a crash or early exit that prevented port assignment","If the backend intentionally isn't running, skip WebUI seeding instead of letting it throw","Make the error message actionable by including backend startup state in logs"],"exampleFix":"// before\nconst port = getBackendPort();\nif (!port) {\n  throw new Error('[WebUI] Cannot start: aioncore is not running (globalThis.__backendPort unset)');\n}\n\n// after (await backend readiness instead of failing)\nawait waitForBackendPort(10_000);\nconst port = getBackendPort();\nif (!port) {\n  throw new Error('[WebUI] Cannot start: aioncore is not running (globalThis.__backendPort unset)');\n}","handlingStrategy":"validation","validationCode":"const port = (globalThis as { __backendPort?: number }).__backendPort;\nif (!port) { /* defer WebUI init until backendManager reports ready */ }","typeGuard":"function isBackendRunning(): boolean {\n  return typeof (globalThis as { __backendPort?: number }).__backendPort === 'number';\n}","tryCatchPattern":"catch (err) { log.error('[WebUI] init deferred:', err.message); /* schedule retry, don't crash app */ }","preventionTips":["Await backend-ready signals before initializing dependent bridges","Expose backend health state, not just a global port variable","Never assume startup ordering; make bridges idempotent/retryable"],"tags":["webui","backend","startup","race-condition"],"backgroundTag":"backend-not-started","analyzedSha":"711aa0550ee183ea495dc33e2c05c7943b70a60a","analyzedAt":"2026-08-28T07:56:06.558Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}