actualbudget/actual · error

Budget file ID is required.

Error message

Budget file ID is required.

What it means

useBuiltInBankSyncProviders throws this when resetting Pluggy.ai credentials while the provider's config source is 'per-budget-file' but no cloud file ID is available. Per-budget-file secrets are stored keyed by the budget file, so without a cloudFileId the 'secret-set' call would target the wrong scope. It is a fail-fast guard before the server request.

Source

Thrown at packages/desktop-client/src/components/banksync/useBuiltInBankSyncProviders.ts:294

      await ensureSuccessResponse(
        await send('secret-set', {
          name: 'simplefin_accessKey',
          value: null,
        }),
        'Failed to clear SimpleFIN access key',
      );
      setIsSimpleFinSetupComplete(false);
    } catch (error) {
      notifyResetFailure('SimpleFIN', error);
    }
  }, [notifyResetFailure]);

  const onPluggyAiReset = useCallback(async () => {
    try {
      const fileId =
        pluggyAiStatus.source === 'per-budget-file' ? cloudFileId : null;
      if (pluggyAiStatus.source === 'per-budget-file' && !fileId) {
        throw new Error(t('Budget file ID is required.'));
      }

      await ensureSuccessResponse(
        await send('secret-set', {
          name: 'pluggyai_clientId',
          value: null,
          fileId,
        }),
        'Failed to clear Pluggy.ai client ID',
      );
      await ensureSuccessResponse(
        await send('secret-set', {
          name: 'pluggyai_clientSecret',
          value: null,
          fileId,
        }),
        'Failed to clear Pluggy.ai client secret',
      );

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Sync the budget to a cloud file (set up a sync server) so a cloudFileId exists before resetting Pluggy.ai credentials
  2. Verify cloudFileId is loaded and non-null before rendering/enabling the Pluggy.ai reset action
  3. If the provider config is not actually per-budget-file, re-check pluggyAiStatus.source before computing fileId

Example fix

// before
const fileId = pluggyAiStatus.source === 'per-budget-file' ? cloudFileId : null;
if (pluggyAiStatus.source === 'per-budget-file' && !fileId) {
  throw new Error(t('Budget file ID is required.'));
}
// after
if (pluggyAiStatus.source === 'per-budget-file' && !cloudFileId) {
  notify('Connect this budget to the cloud before resetting Pluggy.ai credentials.');
  return;
}
const fileId = pluggyAiStatus.source === 'per-budget-file' ? cloudFileId : null;
Defensive patterns

Strategy: validation

Validate before calling

if (pluggyAiStatus.source === 'per-budget-file' && !cloudFileId) {
  throw new Error('Budget file ID is required.');
}
await resetPluggyAi();

Type guard

const hasCloudFile = (v: string | null | undefined): v is string =>
  typeof v === 'string' && v.length > 0;

Try / catch

try {
  await onPluggyAiReset();
} catch (e) {
  if (e instanceof Error && e.message.includes('Budget file ID')) {
    notify('Sync this budget to the cloud before resetting Pluggy.ai credentials.');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling onPluggyAiReset when pluggyAiStatus.source === 'per-budget-file' and cloudFileId is null/undefined (e.g. budget not synced to a cloud file, or local-only budget while using the bank-sync UI).

Common situations: Running the desktop client with a purely local budget (no sync server / no cloud file) and then trying to reset Pluggy.ai credentials; or cloudFileId not yet loaded when the reset button is clicked.

Related errors


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