actualbudget/actual · error
validation-error
validation-error
Error message
err.message (rethrown ValidationError message)
What it means
If exportModel.validate() raises a ValidationError while parsing the imported dashboard (missing fields, wrong data types, unknown widget types), importDashboard rethrows the original message as `Error(err.message, { cause: 'validation-error' })`. The message is the specific validation failure (e.g. "Invalid widget.0.type value ...").
Source
Thrown at packages/loot-core/src/server/dashboard/app.ts:347
]),
),
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;
'dashboard-remove-widget': typeof removeDashboardWidget;
'dashboard-copy-widget': typeof copyDashboardWidget;
'dashboard-import': typeof importDashboard;View on GitHub (pinned to d4334cb6e6)
Solutions
- Read the rethrown message — it names the exact field and index that failed; fix that field in the JSON.
- Compare the file against a freshly exported dashboard from the same Actual version and align the schema.
- Ensure required fields (version, widgets, per-widget type/x/y/width/height, meta for custom-report) are present and correctly typed.
Example fix
// before
{ "widgets": [{ "type": "net-worth-card", "x": "0", "y": 0, "width": 1, "height": 1 }] }
// after
{ "version": 1, "widgets": [{ "type": "net-worth-card", "x": 0, "y": 0, "width": 1, "height": 1 }] } Defensive patterns
Strategy: validation
Validate before calling
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
if (typeof data.version !== 'number' || !Array.isArray(data.widgets)) {
throw new Error('Dashboard file must have numeric version and widgets array');
}
data.widgets.forEach((w, i) => {
for (const f of ['type','x','y','width','height']) {
if (w[f] === undefined) throw new Error(`widgets[${i}] missing ${f}`);
}
for (const f of ['x','y','width','height']) {
if (!Number.isInteger(w[f])) throw new Error(`widgets[${i}].${f} must be an integer`);
}
}); Type guard
function isDashboardExport(v: unknown): v is ExportImportDashboard {
return (
typeof v === 'object' && v !== null &&
typeof (v as any).version === 'number' &&
Array.isArray((v as any).widgets) &&
(v as any).widgets.every((w: any) =>
typeof w.type === 'string' &&
Number.isInteger(w.x) && Number.isInteger(w.y) &&
Number.isInteger(w.width) && Number.isInteger(w.height))
);
} Try / catch
try {
await send('dashboard-import', { filePath, dashboardPageId });
} catch (e) {
if (e.cause === 'validation-error') {
console.error(`Schema problem in import file: ${e.message}`);
}
} Prevention
- Validate the export against the schema before importing.
- Keep export files unmodified between export and import.
- Match export/import versions of Actual to avoid schema drift.
When it happens
Trigger: Importing a dashboard JSON whose structure violates the ExportImportDashboard schema: missing version/widgets, non-integer x/y/width/height, unknown widget type, missing meta on custom-report widgets, or invalid report meta.
Common situations: Schema drift between Actual versions; hand-edited export files; exports from third-party tooling that guesses the format.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid dashboard.widgets data type: it must be an array of
- Invalid catalog format: expected an array
- Field "${field}" does not exist on table ${table}: ${JSON.st
- "${field}" is required for table "${table}": ${JSON.stringif
- Either `filepath` or `buffer` must be given
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/1dc818bad3a10091.
Report an issue: GitHub.