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

  1. Configure a sync server URL in settings before calling key-test
  2. Only call keyTest for files that are synced from a server; use a local key path otherwise
  3. Check getServer()/prefs for SYNC_SERVER before invoking and branch to local key verification
  4. 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

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


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/5740af4f9805a030. Report an issue: GitHub.