{"record":{"id":"a0673f0fd86ffd2d","repo":"actualbudget/actual","slug":"budget-file-id-is-required","errorCode":null,"errorMessage":"Budget file ID is required.","messagePattern":"Budget file ID is required\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop-client/src/components/banksync/useBuiltInBankSyncProviders.ts","lineNumber":294,"sourceCode":"      await ensureSuccessResponse(\n        await send('secret-set', {\n          name: 'simplefin_accessKey',\n          value: null,\n        }),\n        'Failed to clear SimpleFIN access key',\n      );\n      setIsSimpleFinSetupComplete(false);\n    } catch (error) {\n      notifyResetFailure('SimpleFIN', error);\n    }\n  }, [notifyResetFailure]);\n\n  const onPluggyAiReset = useCallback(async () => {\n    try {\n      const fileId =\n        pluggyAiStatus.source === 'per-budget-file' ? cloudFileId : null;\n      if (pluggyAiStatus.source === 'per-budget-file' && !fileId) {\n        throw new Error(t('Budget file ID is required.'));\n      }\n\n      await ensureSuccessResponse(\n        await send('secret-set', {\n          name: 'pluggyai_clientId',\n          value: null,\n          fileId,\n        }),\n        'Failed to clear Pluggy.ai client ID',\n      );\n      await ensureSuccessResponse(\n        await send('secret-set', {\n          name: 'pluggyai_clientSecret',\n          value: null,\n          fileId,\n        }),\n        'Failed to clear Pluggy.ai client secret',\n      );","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/desktop-client/src/components/banksync/useBuiltInBankSyncProviders.ts#L276-L312","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Sync the budget to a cloud file (set up a sync server) so a cloudFileId exists before resetting Pluggy.ai credentials","Verify cloudFileId is loaded and non-null before rendering/enabling the Pluggy.ai reset action","If the provider config is not actually per-budget-file, re-check pluggyAiStatus.source before computing fileId"],"exampleFix":"// before\nconst fileId = pluggyAiStatus.source === 'per-budget-file' ? cloudFileId : null;\nif (pluggyAiStatus.source === 'per-budget-file' && !fileId) {\n  throw new Error(t('Budget file ID is required.'));\n}\n// after\nif (pluggyAiStatus.source === 'per-budget-file' && !cloudFileId) {\n  notify('Connect this budget to the cloud before resetting Pluggy.ai credentials.');\n  return;\n}\nconst fileId = pluggyAiStatus.source === 'per-budget-file' ? cloudFileId : null;","handlingStrategy":"validation","validationCode":"if (pluggyAiStatus.source === 'per-budget-file' && !cloudFileId) {\n  throw new Error('Budget file ID is required.');\n}\nawait resetPluggyAi();","typeGuard":"const hasCloudFile = (v: string | null | undefined): v is string =>\n  typeof v === 'string' && v.length > 0;","tryCatchPattern":"try {\n  await onPluggyAiReset();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Budget file ID')) {\n    notify('Sync this budget to the cloud before resetting Pluggy.ai credentials.');\n  } else throw e;\n}","preventionTips":["Disable provider reset buttons until a cloudFileId exists","Check pluggyAiStatus.source before offering per-budget-file actions","Keep local-only budgets away from per-budget-file provider flows"],"tags":["banksync","budget-file","config","client-side"],"backgroundTag":"missing-budget-file-id","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}