actualbudget/actual · error · ValidationError
Invalid widget.${idx}.y data-type for value ${widget.y}.
Error message
Invalid widget.${idx}.y data-type for value ${widget.y}. What it means
Each widget's y (grid row position) must be an integer. The dashboard import validator throws this ValidationError when widget.y is fractional, a string, null, or missing, since the grid layout requires whole-number rows.
Source
Thrown at packages/loot-core/src/server/dashboard/app.ts:79
dashboard.widgets.forEach((widget, idx) => {
requiredFields(`Dashboard widget #${idx}`, widget, [
'type',
'x',
'y',
'width',
'height',
...(isExportedCustomReportWidget(widget) ? ['meta' as const] : []),
]);
if (!Number.isInteger(widget.x)) {
throw new ValidationError(
`Invalid widget.${idx}.x data-type for value ${widget.x}.`,
);
}
if (!Number.isInteger(widget.y)) {
throw new ValidationError(
`Invalid widget.${idx}.y data-type for value ${widget.y}.`,
);
}
if (!Number.isInteger(widget.width)) {
throw new ValidationError(
`Invalid widget.${idx}.width data-type for value ${widget.width}.`,
);
}
if (!Number.isInteger(widget.height)) {
throw new ValidationError(
`Invalid widget.${idx}.height data-type for value ${widget.height}.`,
);
}
if (!isWidgetType(widget.type)) {
throw new ValidationError(View on GitHub (pinned to d4334cb6e6)
Solutions
- Set widget.y = Math.round(widget.y) before import.
- Ensure every widget has an explicit integer y (e.g. sequential row indices).
- Coerce strings with Number() and verify with Number.isInteger.
- Fix the generator to compute rows with integer counters, not division results.
- Re-export from the app for a valid baseline.
Example fix
// before
let y = 0; for (const w of defs) { w.y = y; y += w.height / 2; }
// after
let y = 0; for (const w of defs) { w.y = y; y += Math.ceil(w.height); } Defensive patterns
Strategy: validation
Validate before calling
widgets.forEach((w, i) => {
if (!Number.isInteger(w.y)) throw new Error(`Widget #${i}: y must be an integer, got ${w.y}`);
}); Type guard
function hasIntegerRow(w: { y: unknown }): w is { y: number } {
return Number.isInteger(w.y);
} Try / catch
try {
await send('dashboard-import', { version: 1, widgets });
} catch (e) {
if (e instanceof ValidationError && e.message.includes('.y data-type')) {
console.error('Non-integer y coordinate in import; round rows and retry');
} else throw e;
} Prevention
- Compute row positions with integer counters, never division.
- Pre-flight check every widget's y with Number.isInteger.
- Assign sequential integer rows when generating layouts.
- Re-export from the app if unsure of the correct schema.
When it happens
Trigger: Importing dashboard JSON where a widget's y is 2.5, "1", null, or undefined; generated exports using float row math or omitting y entirely.
Common situations: Scripted dashboard generation stacking widgets with computed float offsets; JSON edited in a spreadsheet that emits string numerics; exports from tooling that forgot the y field.
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 widget.${idx}.x data-type for value ${widget.x}.
- Invalid widget.${idx}.width data-type for value ${widget.wid
- Invalid widget.${idx}.height data-type for value ${widget.he
- Invalid dashboard.widgets data type: it must be an array of
- Invalid widget.${idx}.type value ${String(widget.type)}.
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/3166e68be9358782.
Report an issue: GitHub.