actualbudget/actual · error
No sync server configured.
Error message
No sync server configured.
What it means
keyTest validates a password against the key stored on the sync server by POSTing to /user-get-key, so it requires a configured sync server (getServer()). When no server URL is configured it throws 'No sync server configured.' before making any network request.
Source
Thrown at packages/loot-core/src/server/encryption/app.ts:79
cloudFileId?: Budget['cloudFileId'];
password: string;
}) {
const userToken = await asyncStorage.getItem('user-token');
if (cloudFileId == null) {
cloudFileId = prefs.getPrefs().cloudFileId;
}
let validCloudFileId: NonNullable<Budget['cloudFileId']>;
let res: {
id: string;
salt: string;
test: string | null;
};
try {
const serverConfig = getServer();
if (!serverConfig) {
throw new Error('No sync server configured.');
}
res = await post(serverConfig.SYNC_SERVER + '/user-get-key', {
token: userToken,
fileId: cloudFileId,
});
validCloudFileId = cloudFileId!;
} catch (e) {
logger.log(e);
return { error: { reason: 'network' } };
}
const { id, salt, test: originalTest } = res;
if (!originalTest) {
return { error: { reason: 'old-key-style' } };
}
const test: {View on GitHub (pinned to d4334cb6e6)
Solutions
- Configure a sync server URL in settings before calling key-test
- Only call keyTest for files that are synced from a server; use a local key path otherwise
- Check getServer()/prefs for SYNC_SERVER before invoking and branch to local key verification
- Re-enter server settings if a config reset wiped the URL
Example fix
// before
const ok = await send('key-test', { password, cloudFileId });
// after
if (getServer()) {
const ok = await send('key-test', { password, cloudFileId });
} else {
throw new Error('Key testing requires a configured sync server');
} Defensive patterns
Strategy: validation
Validate before calling
const serverConfig = getServer();
if (!serverConfig || !serverConfig.SYNC_SERVER) {
throw new Error('Configure a sync server before testing cloud encryption keys');
} Type guard
function hasSyncServer(cfg: { SYNC_SERVER?: string } | null): cfg is { SYNC_SERVER: string } {
return !!cfg && typeof cfg.SYNC_SERVER === 'string' && cfg.SYNC_SERVER.length > 0;
} Try / catch
try {
const valid = await send('key-test', { password, cloudFileId });
} catch (e) {
if (e.message === 'No sync server configured.') {
promptUserForServerSettings();
} else throw e;
} Prevention
- Only use key-test for files that came from a sync server
- Check server config in prefs before enabling cloud-key UI features
- Persist the server URL and detect config resets early
- For local-only budgets, use local key verification paths instead
When it happens
Trigger: Calling keyTest (user-test-key handler) in a local-only setup with no server URL set in prefs; the server config was cleared or never entered on the 'no server' path; testing a cloud-file key for a file opened without sync.
Common situations: Local-first users enabling encryption without a sync server; config migration losing the server URL; automation running against a budget file downloaded manually rather than via sync.
Related errors
- Failed to get server config.
- No sync server configured.
- load-key-error
- getServerErrorReason(json)
- network-failure
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/5740af4f9805a030.
Report an issue: GitHub.