{"record":{"id":"29197227c9496390","repo":"actualbudget/actual","slug":"authentication-failed-result-error","errorCode":null,"errorMessage":"Authentication failed: ${result.error}","messagePattern":"Authentication failed: (.+?)","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/main.ts","lineNumber":324,"sourceCode":"          'token-expired',\n        );\n      }\n      if (user.offline === true) {\n        // Clear token since we can't validate\n        await runHandler(handlers['subscribe-set-token'], { token: '' });\n        throw withErrorCode(\n          new Error('Authentication failed: server offline or unreachable'),\n          'network-failure',\n        );\n      }\n    } else if ('password' in config && config.password) {\n      const result = await runHandler(handlers['subscribe-sign-in'], {\n        password: config.password,\n      });\n      if (result?.error) {\n        // `result.error` is already a machine-readable slug (e.g.\n        // 'invalid-password', 'network-failure')\n        throw withErrorCode(\n          new Error(`Authentication failed: ${result.error}`),\n          result.error,\n        );\n      }\n    }\n  } else {\n    // This turns off all server URLs. In this mode we don't want any\n    // access to the server, we are doing things locally\n    setServer(null);\n\n    app.events.on('load-budget', () => {\n      setSyncingMode('offline');\n    });\n  }\n\n  return lib;\n}\n","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/main.ts#L306-L342","documentation":"During init() with password-based config, 'subscribe-sign-in' is called. If the handler returns an error slug (e.g. 'invalid-password' or 'network-failure'), an Error with the message 'Authentication failed: <slug>' is thrown and tagged with that slug as the error code. The message body is a machine-readable slug, so parse the code rather than the text.","triggerScenarios":"Calling init({ URL, password }) where the password is wrong ('invalid-password') or the sign-in handler fails with another slug such as 'network-failure' — the exact reason is in both the error code and message suffix.","commonSituations":"Typo in the server password or password changed on the server; connecting to a fresh server where the user has not been set up; wrong server URL so sign-in fails at the network level.","solutions":["Read the error code / message suffix: it is the machine-readable reason","If 'invalid-password', re-enter or reset the sync server password","Verify the server URL points at the intended sync server","If 'network-failure', fix connectivity to the server first, then retry sign-in"],"exampleFix":"// before\nawait init({ URL: serverUrl, password: 'old-pass' });\n// after (handle the slug)\ntry {\n  await init({ URL: serverUrl, password });\n} catch (e) {\n  if (e.code === 'invalid-password') {\n    promptUserForPassword();\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"type-guard","validationCode":"// Validate inputs before calling init with password auth\nif (!serverUrl.startsWith('http')) throw new Error('Server URL must be http(s)');\nif (!password || password.length === 0) throw new Error('Password required for server auth');","typeGuard":"function isAuthFailure(e: unknown): e is Error & { code: string } {\n  return (\n    e instanceof Error &&\n    e.message.startsWith('Authentication failed:') &&\n    typeof (e as { code?: string }).code === 'string'\n  );\n}","tryCatchPattern":"try {\n  await init({ URL: serverUrl, password });\n} catch (e) {\n  if (isAuthFailure(e)) {\n    switch (e.code) {\n      case 'invalid-password': return promptPasswordRetry();\n      case 'network-failure': return scheduleRetry();\n      default: throw e;\n    }\n  }\n  throw e;\n}","preventionTips":["Branch on the error code (message suffix), never on the full message text — the slug is the stable contract","Store the server password securely, not hardcoded, and update it when rotated","Confirm the user exists on the target server before password sign-in","Handle 'invalid-password' interactively so a stale password doesn't crash startup"],"tags":["authentication","password","sync-server"],"backgroundTag":"invalid-credentials","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}