{"record":{"id":"168a91cc4ac76a45","repo":"NousResearch/hermes-agent","slug":"first-run-remote-setup-completed-without-a-saved-r","errorCode":null,"errorMessage":"First-run remote setup completed without a saved remote backend.","messagePattern":"First-run remote setup completed without a saved remote backend\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/primary-backend-startup.ts","lineNumber":54,"sourceCode":"}: PrimaryBackendStartupOptions<Backend, RuntimeBackend, Remote, Connection>): Promise<\n  PrimaryBackendStartupResult<RuntimeBackend, Connection>\n> {\n  const savedRemote = await resolveRemote()\n\n  if (savedRemote) {\n    return { kind: 'remote', connection: await connectRemote(savedRemote) }\n  }\n\n  await waitForLocalStart()\n\n  const backend = await prepareLocalBackend()\n  const decision = await waitForDecision(backend)\n\n  if (decision === 'remote-applied') {\n    const appliedRemote = await resolveRemote()\n\n    if (!appliedRemote) {\n      throw new Error('First-run remote setup completed without a saved remote backend.')\n    }\n\n    return { kind: 'remote', connection: await connectRemote(appliedRemote) }\n  }\n\n  if (decision === 'reset') {\n    throw new FirstRunSetupResetError()\n  }\n\n  return { kind: 'local', backend: await ensureLocalRuntime(backend) }\n}\n","sourceCodeStart":36,"sourceCodeEnd":66,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/primary-backend-startup.ts#L36-L66","documentation":"Thrown during first-run backend startup in the Hermes desktop app. When waitForDecision(backend) returns 'remote-applied', the code re-resolves the saved remote backend; if resolveRemote() returns nothing, the wizard claimed the remote was applied but nothing was persisted. This is an internal invariant failure, not a user-input error.","triggerScenarios":"decision === 'remote-applied' but a subsequent resolveRemote() yields null/undefined — the wizard's apply step failed to persist, wrote to a different location/key than resolveRemote() reads, or a concurrent reset/clear removed the config between apply and resolve.","commonSituations":"Config write race during first run (app quit or another window cleared config mid-wizard); a version mismatch where the wizard persists the remote under a key or schema the resolver does not read; permissions failure writing the config file so the apply write failed silently.","solutions":["Compare the wizard's apply-step write (file, key, schema) against exactly what resolveRemote() reads — a mismatch is the usual cause.","Re-run first-run setup (reset the first-run marker) and walk the remote wizard again; if it persists this time, the first attempt hit a transient write failure.","Check filesystem permissions and disk space where the remote config is stored so writes cannot fail silently.","If reproducible, instrument the 'remote-applied' branch to log the result of the apply write immediately after it returns."],"exampleFix":"// before\nif (decision === 'remote-applied') {\n  const appliedRemote = await resolveRemote()\n  if (!appliedRemote) throw new Error('First-run remote setup completed without a saved remote backend.')\n  return { kind: 'remote', connection: await connectRemote(appliedRemote) }\n}\n\n// after (fall back to the already-prepared local backend instead of crashing first run)\nif (decision === 'remote-applied') {\n  const appliedRemote = await resolveRemote()\n  if (!appliedRemote) {\n    log.error('remote-applied but resolveRemote() empty; remote config never persisted')\n    return { kind: 'local', backend: await ensureLocalRuntime(backend) }\n  }\n  return { kind: 'remote', connection: await connectRemote(appliedRemote) }\n}","handlingStrategy":"try-catch","validationCode":"if (decision === 'remote-applied') {\n  const appliedRemote = await resolveRemote()\n  if (!appliedRemote) {\n    // fall back to the already-prepared local backend rather than crashing first run\n    return { kind: 'local', backend: await ensureLocalRuntime(backend) }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await startPrimaryBackend()\n} catch (e) {\n  if (e instanceof Error && e.message === 'First-run remote setup completed without a saved remote backend.') {\n    // the remote config never landed: re-run the first-run wizard\n    return await startFirstRunWizard()\n  }\n  if (e instanceof FirstRunSetupResetError) return null // user reset: expected path\n  throw e\n}","preventionTips":["Verify config writes in the wizard's apply step with a read-back check.","Keep the wizard's write key/schema and resolveRemote()'s read key/schema in one shared constant.","Guard config writes against concurrent clears with a lock or single-writer rule."],"tags":["desktop","first-run","remote-backend","invariant"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}