actualbudget/actual · error

json-parse-error

json-parse-error

Error message

Invalid JSON file.

What it means

When JSON.parse of the imported file throws a SyntaxError, importDashboard converts it into `Error('Invalid JSON file.', { cause: 'json-parse-error' })`. The cause code lets the client distinguish malformed JSON from validation or internal failures.

Source

Thrown at packages/loot-core/src/server/dashboard/app.ts:344

                Object.entries(reportModel.fromJS(meta)).map(([key, value]) => [
                  key,
                  value ?? null,
                ]),
              ),
              tombstone: false,
            }),
          ),
      ]);
    });

    return { status: 'ok' as const };
  } catch (err: unknown) {
    if (err instanceof Error) {
      err.message = 'Error importing file: ' + err.message;
      captureException(err);
    }
    if (err instanceof SyntaxError) {
      throw new Error('Invalid JSON file.', { cause: 'json-parse-error' });
    }
    if (err instanceof ValidationError) {
      throw new Error(err.message, { cause: 'validation-error' });
    }
    throw new Error('Internal error occurred during import.', {
      cause: 'internal-error',
    });
  }
}

export type DashboardHandlers = {
  'dashboard-create': typeof createDashboardPage;
  'dashboard-delete': typeof deleteDashboardPage;
  'dashboard-rename': typeof renameDashboardPage;
  'dashboard-update': typeof updateDashboard;
  'dashboard-update-widget': typeof updateDashboardWidget;
  'dashboard-reset': typeof resetDashboard;
  'dashboard-add-widget': typeof addDashboardWidget;

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Validate the file locally with `JSON.parse(fs.readFileSync(p,'utf8'))` or `jq . file.json` to find the syntax error.
  2. Re-export the dashboard from Actual and use the fresh file unmodified.
  3. Ensure the file is saved as UTF-8 without BOM and ends cleanly.

Example fix

// before (broken JSON)
{ "version": 1, "widgets": [ {...}, ] }
// after
{ "version": 1, "widgets": [ {...} ] }
Defensive patterns

Strategy: validation

Validate before calling

try {
  JSON.parse(fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, ''));
} catch (e) {
  throw new Error(`Import file is not valid JSON: ${(e as SyntaxError).message}`);
}

Type guard

function isValidJson(text: string): boolean {
  try { JSON.parse(text); return true; } catch { return false; }
}

Try / catch

try {
  await send('dashboard-import', { filePath, dashboardPageId });
} catch (e) {
  if (e.cause === 'json-parse-error') {
    console.error('The dashboard file is not valid JSON; re-export it.');
  }
}

Prevention

When it happens

Trigger: Importing a dashboard file that is empty, truncated, contains trailing commas/comments, is not JSON at all (e.g. an HTML error page), or has a BOM/encoding issue.

Common situations: Downloading the export link and saving an error page; manually editing the file and breaking JSON; partial file transfer.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


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