actualbudget/actual · error · Error

No sync server set

Error message

No sync server set

What it means

saveMetadataPrefs (packages/loot-core/src/server/preferences/app.ts:220) throws this plain Error when it needs to push the budget name to the server (prefsToSet.budgetName with a cloudFileId present) but no sync server URL is configured — getServer()?.SYNC_SERVER is undefined. It typically means the client is running without a server base URL set (server-only mode URLs absent from the environment/config).

Source

Thrown at packages/loot-core/src/server/preferences/app.ts:220

        ? true
        : notifyWhenUpdateIsAvailable, // default to true
  };
}

async function saveMetadataPrefs(prefsToSet: MetadataPrefs) {
  if (!prefsToSet) {
    return 'ok';
  }

  const { cloudFileId } = _getMetadataPrefs();

  // Need to sync the budget name on the server as well
  if (prefsToSet.budgetName && cloudFileId) {
    const userToken = await asyncStorage.getItem('user-token');

    const syncServer = getServer()?.SYNC_SERVER;
    if (!syncServer) {
      throw new Error('No sync server set');
    }

    await post(syncServer + '/update-user-filename', {
      token: userToken,
      fileId: cloudFileId,
      name: prefsToSet.budgetName,
    });
  }

  await _saveMetadataPrefs(prefsToSet);
  return 'ok';
}

async function loadMetadataPrefs(): Promise<MetadataPrefs> {
  return _getMetadataPrefs();
}

async function saveServerPrefs({ prefs }: { prefs: Record<string, string> }) {

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Configure the sync server URL so getServer().SYNC_SERVER is defined (set the server base URL in the sync-server config/environment serving the frontend).
  2. If you don't use sync, rename the budget without a cloudFileId (local-only budget).
  3. Restart the deployment after adding the server URL so the config propagates to the client.
  4. Verify with the deployed app that /update-user-filename is reachable once the URL is set.

Example fix

// before: frontend served without sync server configured (SYNC_SERVER undefined)
// after: in sync-server config / environment
// .env: ACTUAL_SERVER_URL=https://sync.example.com
// restart sync-server so the client receives SYNC_SERVER in getServer()
Defensive patterns

Strategy: validation

Validate before calling

const syncServer = getServer()?.SYNC_SERVER;
if (prefsToSet.budgetName && cloudFileId && !syncServer) {
  // don't attempt the rename sync; warn the user the server URL is not configured
  logger.log('Skipping budget-name sync: no sync server configured');
  return;
}

Type guard

function hasSyncServer(cfg: unknown): cfg is { SYNC_SERVER: string } {
  return typeof cfg === 'object' && cfg !== null && typeof (cfg as any).SYNC_SERVER === 'string' && (cfg as any).SYNC_SERVER.length > 0;
}

Try / catch

try {
  await savePrefs(prefsToSet);
} catch (e) {
  if (e instanceof Error && e.message === 'No sync server set') {
    // prompt the user to configure the server URL, or proceed without cloud rename
    showConfigureServerDialog();
  } else throw e;
}

Prevention

When it happens

Trigger: Renaming a budget (saving metadata with a new budgetName) while a cloudFileId exists, in a build where SYNC_SERVER is not configured — e.g. the web frontend served without the sync server URL configured, or a desktop build in local-only mode that somehow has a cloudFileId.

Common situations: Self-hosting the frontend without setting the sync server URL in the server config; missing ACTUAL_SERVER_URL-style environment variable; using a build of the app compiled without server endpoints; renamed cloud budgets after switching from a server-less deployment.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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