actualbudget/actual · error

not-configured

not-configured

Error message

Pluggy credentials are not configured

What it means

For POST /status (or /accounts), after fileId checks the server calls pluggyaiService.getCredentialSource(fileId); when no Pluggy credential source is stored for that budget it returns HTTP 400 with reason 'not-configured' and details 'Pluggy credentials are not configured'. The Pluggy.ai integration requires per-budget stored credentials (client id/secret or source id) before it can query Pluggy.

Source

Thrown at packages/sync-server/src/app-pluggyai/app-pluggyai.js:88

          details: 'invalid fileId',
        });
        return;
      }

      if (!canAccessFile(fileId, res.locals.user_id)) {
        res.status(403).send({
          status: 'error',
          reason: 'file-access-denied',
          details: "You don't have permissions over this file",
        });
        return;
      }
    }

    try {
      const source = pluggyaiService.getCredentialSource(fileId);
      if (!source) {
        res.status(400).send({
          status: 'error',
          reason: 'not-configured',
          details: 'Pluggy credentials are not configured',
        });
        return;
      }

      const credentialFileId = source === 'per-budget-file' ? fileId : null;
      const itemIds = (
        secretsService.get(SecretName.pluggyai_itemIds, credentialFileId) ?? ''
      )
        .split(',')
        .map(item => item.trim())
        .filter(Boolean);

      let accounts = [];

      for (const item of itemIds) {

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Configure Pluggy credentials for the budget via the integration's config endpoint (or the app UI) before calling /status
  2. Set the required Pluggy environment variables on the sync-server (e.g. PLUGGY_CLIENT_ID/PLUGGY_CLIENT_SECRET) and restart it
  3. Confirm the fileId used is the same budget where credentials were saved
  4. Re-save credentials if a database restore dropped them

Example fix

// before
curl -X POST /pluggyai/status -H 'X-Actual-File-Id: <id>'  // 400 not-configured
// after
curl -X POST /pluggyai/configure -d '{"clientId":"...","clientSecret":"..."}' -H 'X-Actual-File-Id: <id>'
curl -X POST /pluggyai/status -H 'X-Actual-File-Id: <id>'
Defensive patterns

Strategy: fallback

Validate before calling

// pre-check via /status before dependent calls; treat not-configured as setup-needed
const res = await fetch('/pluggyai/status', { headers: { 'X-Actual-File-Id': fileId, ...authHeaders } });
const body = await res.json();
if (body.status === 'error' && body.reason === 'not-configured') {
  throw new Error('Run Pluggy configuration for this budget first');
}

Try / catch

const res = await fetch('/pluggyai/accounts', { method: 'POST', headers, body });
if (res.status === 400) {
  const body = await res.json();
  if (body.reason === 'not-configured') {
    await configurePluggyCredentials(fileId, clientId, clientSecret);
    return retry(); // single retry after configuration
  }
}

Prevention

When it happens

Trigger: POST /status or /accounts with a valid, accessible fileId for which no Pluggy credentials have ever been saved via the integration's configuration endpoint.

Common situations: Fresh budget never configured for Pluggy; credentials cleared after a server reset/DB restore; testing endpoints before completing the Pluggy setup step; missing PLUGGY_AI_* env-based configuration.

Related errors


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