actualbudget/actual · error · Error
network-failure
network-failure
Error message
Authentication failed: server offline or unreachable
What it means
During init(), after validating the stored token, the code checks user.offline. If the server reports itself offline (or unreachable when validating), the token is cleared and this error is thrown with code 'network-failure'. It signals the sync server could not be reached or is in an offline state, not a bad credential.
Source
Thrown at packages/loot-core/src/server/main.ts:312
if ('sessionToken' in config && config.sessionToken) {
// Session token authentication
await runHandler(handlers['subscribe-set-token'], {
token: config.sessionToken,
});
// Validate the token
const user = await runHandler(handlers['subscribe-get-user'], undefined);
if (!user || user.tokenExpired === true) {
// Clear invalid token
await runHandler(handlers['subscribe-set-token'], { token: '' });
throw withErrorCode(
new Error('Authentication failed: invalid or expired session token'),
'token-expired',
);
}
if (user.offline === true) {
// Clear token since we can't validate
await runHandler(handlers['subscribe-set-token'], { token: '' });
throw withErrorCode(
new Error('Authentication failed: server offline or unreachable'),
'network-failure',
);
}
} else if ('password' in config && config.password) {
const result = await runHandler(handlers['subscribe-sign-in'], {
password: config.password,
});
if (result?.error) {
// `result.error` is already a machine-readable slug (e.g.
// 'invalid-password', 'network-failure')
throw withErrorCode(
new Error(`Authentication failed: ${result.error}`),
result.error,
);
}
}
} else {View on GitHub (pinned to d4334cb6e6)
Solutions
- Check the sync server is running and reachable at the configured URL (curl the server health endpoint)
- Correct the server URL in the client configuration
- Check network/firewall/proxy rules between client and server
- If the server intentionally runs offline, reconfigure the client for local-only use or restore server connectivity
Example fix
// before
await init({ URL: 'http://localhost:5007', TOKEN }); // wrong port
// after
await init({ URL: 'http://localhost:5006', TOKEN }); // correct sync-server port Defensive patterns
Strategy: retry
Validate before calling
// Probe the server before init
const res = await fetch(`${serverUrl}/health`, { method: 'GET' }).catch(() => null);
if (!res || !res.ok) {
throw new Error(`Sync server unreachable at ${serverUrl}`);
} Type guard
function isNetworkFailureError(e: unknown): e is Error & { code: 'network-failure' } {
return e instanceof Error && (e as { code?: string }).code === 'network-failure';
} Try / catch
try {
await init({ URL: serverUrl, TOKEN });
} catch (e) {
if (isNetworkFailureError(e)) {
await delay(2000);
return init({ URL: serverUrl, TOKEN }); // single bounded retry after connectivity check
}
throw e;
} Prevention
- Health-check the sync server URL before calling init
- Verify port (default 5006) and protocol (http/https) in the client config
- Distinguish 'network-failure' from 'token-expired': only the former is retryable
- Alert on server uptime if clients depend on sync; self-hosted servers behind proxies need keepalive checks
When it happens
Trigger: Calling init() with a token-based config when 'subscribe-get-user' returns offline:true — server down, wrong URL/port, DNS failure, or the server explicitly set to offline mode.
Common situations: Sync server not started or crashed; misconfigured server URL in client settings; firewall/proxy blocking the server; self-hosted server behind an unreachable host in remote environments.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No sync server configured.
- getServerErrorReason(json)
- network-failure
- parse-json
- responseData.description || responseData.reason || 'unknown'
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/062e3696d72c9db3.
Report an issue: GitHub.