{"record":{"id":"28842726645fcc66","repo":"different-ai/openwork","slug":"openwork-server-did-not-become-ready-after-activat","errorCode":null,"errorMessage":"OpenWork server did not become ready after activation.","messagePattern":"OpenWork server did not become ready after activation\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"apps/app/src/react-app/shell/desktop-local-openwork.ts","lineNumber":174,"sourceCode":"\n  try {\n    const engine = await engineInfo().catch(() => null) as EngineInfo | null;\n    let startedEngine = false;\n    if (!engine?.running || !engine.baseUrl) {\n      await engineStart(workspaceRoot, {\n        runtime: \"direct\",\n        workspacePaths,\n        openworkRemoteAccess: readOpenworkServerSettings().remoteAccessEnabled === true,\n      });\n      startedEngine = true;\n    }\n\n    // The server publishes its base URL and tokens asynchronously after a\n    // (re)start, so gate on observed readiness with bounded retries instead\n    // of failing on the first empty answer.\n    const info = await waitForReadyLocalOpenworkServerInfo();\n    if (!isReadyLocalOpenworkServerInfo(info) || !info.baseUrl) {\n      throw new Error(\"OpenWork server did not become ready after activation.\");\n    }\n\n    const previousSettings = readOpenworkServerSettings();\n    const nextSettings = writeOpenworkServerSettings({\n      urlOverride: info.baseUrl,\n      token: info.ownerToken?.trim() || info.clientToken?.trim() || undefined,\n      hostToken: info.hostToken?.trim() || undefined,\n      portOverride: info.port ?? undefined,\n      remoteAccessEnabled: info.remoteAccessEnabled === true,\n    });\n    if (startedEngine || openworkServerSettingsChanged(previousSettings, nextSettings)) {\n      emitOpenworkSettingsChanged();\n    }\n\n    recordInspectorEvent(\"route.local_openwork.ensure.success\", {\n      route: options.route,\n      workspaceId: workspace.id,\n      workspaceRoot,","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/shell/desktop-local-openwork.ts#L156-L192","documentation":"Thrown by ensureDesktopLocalOpenworkConnection after the bounded retry loop for waitForReadyLocalOpenworkServerInfo gives up. The local OpenWork server publishes its base URL and tokens asynchronously after a (re)start; if the info never becomes ready within the retries, this error reports that the server did not become ready after activation.","triggerScenarios":"Calling ensureDesktopLocalOpenworkConnection (from useWorkspaceRouteState, handleCreateWorkspace, or SettingsRouteContent) right after server start/restart when the info file with baseUrl/token never appears before retries are exhausted.","commonSituations":"Slow machine or first-run install where the local server takes longer than the retry budget to boot; server process crashed during startup; stale server state file deleted while the process is dead; port conflicts preventing the server from publishing its URL.","solutions":["Retry the activation — a slow start often succeeds on a second attempt.","Check local server logs/process to confirm the openwork-server actually started (crash, port conflict).","Increase the retry budget/timeout in waitForReadyLocalOpenworkServerInfo if starts are routinely slow.","Fully restart the desktop app so the local server is launched fresh."],"exampleFix":"// before\nif (!isReadyLocalOpenworkServerInfo(info) || !info.baseUrl) {\n  throw new Error(\"OpenWork server did not become ready after activation.\");\n}\n// after — one extra explicit wait before failing\nif (!isReadyLocalOpenworkServerInfo(info) || !info.baseUrl) {\n  info = await waitForReadyLocalOpenworkServerInfo({ extraTimeoutMs: 15000 });\n  if (!isReadyLocalOpenworkServerInfo(info) || !info.baseUrl) throw new Error(\"OpenWork server did not become ready after activation.\");\n}","handlingStrategy":"retry","validationCode":"const ready = await isLocalOpenworkServerInfoReady();\nif (!ready) await retryActivationWithBackoff();","typeGuard":"function isServerInfoReady(info: LocalOpenworkServerInfo | null): info is LocalOpenworkServerInfo & { baseUrl: string } {\n  return info != null && typeof info.baseUrl === \"string\" && info.baseUrl.length > 0;\n}","tryCatchPattern":"try {\n  await ensureDesktopLocalOpenworkConnection(options);\n} catch (error) {\n  if (error.message.includes(\"did not become ready\")) {\n    await retryWithBackoff(() => ensureDesktopLocalOpenworkConnection(options), 3);\n  } else throw error;\n}","preventionTips":["Use exponential backoff with a generous total timeout for server readiness.","Monitor the server process health, not just the info file.","Pre-warm the local server at app startup before routes need it.","Alert on port conflicts and stale state files."],"tags":["startup","timeout","local-server","retry-exhausted"],"backgroundTag":"server-not-ready","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}