actualbudget/actual · error

response.reason || response.error || fallbackMessage

Error message

response.reason || response.error || fallbackMessage

What it means

The second branch of `ensureSuccessResponse`: when the sync-server response carries an `error` (without an `error_code`), it throws `response.reason || response.error || fallbackMessage`. The `fallbackMessage` (passed by each provider's reset handler, e.g. 'Failed to set GoCardless secret') is only used when neither `reason` nor `error` carry text. This is the generic failure path for provider secret-set calls.

Source

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

  }

  if (isAdmin) {
    return null;
  }

  return isFileOwner ? 'file-owner' : 'general';
}

async function ensureSuccessResponse(
  response: SecretSetResponse,
  fallbackMessage: string,
) {
  if (response?.error_code) {
    throw new Error(response.reason || response.error_code);
  }

  if (response?.error) {
    throw new Error(response.reason || response.error || fallbackMessage);
  }
}

export function useBuiltInBankSyncProviders({
  upgradingAccountId,
}: UseBuiltInBankSyncProvidersOptions = {}) {
  const { t } = useTranslation();
  const dispatch = useDispatch();
  const syncServerStatus = useSyncServerStatus();
  const { cloudFileId, isAdmin, isFileOwner } = useCurrentAccess();
  const canConfigureProviders = isAdmin;

  const [isGoCardlessSetupComplete, setIsGoCardlessSetupComplete] = useState<
    boolean | null
  >(null);
  const [isSimpleFinSetupComplete, setIsSimpleFinSetupComplete] = useState<
    boolean | null
  >(null);

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Check the sync-server logs at the time of the request — the thrown message's `reason`/`error` text points to the server-side cause.
  2. Verify the sync-server is online and reachable (`syncServerStatus`) and the user has admin rights before configuring providers.
  3. Confirm server storage (secrets table / key store) is writable and the server version matches the client.
  4. Retry the credential submission after fixing the server-side condition; if the message equals the generic fallback only, add logging to capture the full server response.

Example fix

// before
await ensureSuccessResponse(res, 'Failed to set Akahu secret');
// after
try {
  await ensureSuccessResponse(res, 'Failed to set Akahu secret');
} catch (e) {
  logger.error('Akahu secret-set failed', { response: res });
  setError(e.message === 'Failed to set Akahu secret'
    ? 'Unknown server error — check sync-server logs'
    : e.message);
}
Defensive patterns

Strategy: fallback

Validate before calling

if (syncServerStatus !== 'online') {
  setError('Bank sync requires a connected sync server. Start the server and sign in first.');
  return;
}
if (!isAdmin) { setError('Only admins can configure bank-sync providers.'); return; }

Type guard

function hasServerError(
  res: SecretSetResponse,
): res is SecretSetResponse & { error: string } {
  return typeof res?.error === 'string' && res.error.length > 0;
}

Try / catch

try {
  await ensureSuccessResponse(res, 'Failed to set secret');
} catch (e) {
  const msg = e instanceof Error ? e.message : String(e);
  if (msg === fallbackMessage) {
    // Neither reason nor error had text — capture raw response for support
    logger.error('secret-set failed with no reason', { res });
    setError(fallbackMessage + ' (check sync-server logs for details)');
  } else {
    setError(msg);
  }
}

Prevention

When it happens

Trigger: A reset/save of any bank-sync provider secret (GoCardless, SimpleFin, PluggyAI, EnableBanking, Akahu) where the sync-server returns `{ error: '...' }` with no `error_code` — server-side exception during secret storage, network/DB failure on the server, or provider upstream call failing with only a free-form error string.

Common situations: Self-hosted sync-server with database/storage issues; server unreachable mid-request returning a wrapped error; provider API outage causing upstream failure surfaced as a plain error; unauthenticated request to the sync-server.

Related errors


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