koala73/worldmonitor · error · DashboardPanelCatalogError
invalid_limit
invalid_limit
Error message
limit must be an integer from 1 to ${DASHBOARD_PANEL_CATALOG_MAX_LIMIT}. What it means
listDashboardPanelCatalog() clamps page size via query.limit, defaulting to DASHBOARD_PANEL_CATALOG_DEFAULT_LIMIT (6) with a hard maximum DASHBOARD_PANEL_CATALOG_MAX_LIMIT (8). A limit that is not an integer or is outside 1..8 throws DashboardPanelCatalogError with reason 'invalid_limit'; it does not silently clamp, so callers must pre-validate.
Source
Thrown at src/services/webmcp-panel-catalog.ts:206
typeof cursor !== 'string'
|| cursor.length > DASHBOARD_PANEL_ID_MAX_CHARS
|| !PANEL_ID_RE.test(cursor)
|| !CANONICAL_PANEL_ID_SET.has(cursor)
) {
throw new DashboardPanelCatalogError(
'invalid_cursor',
'cursor is not a valid catalog cursor.',
);
}
}
const limit = query.limit ?? DASHBOARD_PANEL_CATALOG_DEFAULT_LIMIT;
if (
!Number.isInteger(limit)
|| limit < 1
|| limit > DASHBOARD_PANEL_CATALOG_MAX_LIMIT
) {
throw new DashboardPanelCatalogError(
'invalid_limit',
`limit must be an integer from 1 to ${DASHBOARD_PANEL_CATALOG_MAX_LIMIT}.`,
);
}
const catalogVariant = variantFilter ?? currentVariant;
const registryIds = getCanonicalDashboardPanelIds(variantFilter);
const items: DashboardPanelCatalogItem[] = [];
for (const panelId of registryIds) {
const item = describePanel(panelId, live, catalogVariant);
if (categoryFilter !== undefined && item.category !== categoryFilter) continue;
if (query.enabled !== undefined && item.enabled !== query.enabled) continue;
if (query.available !== undefined && item.available !== query.available) continue;
items.push(item);
}
const startIndex = cursor === undefined
? 0View on GitHub (pinned to 9361220cc0)
Solutions
- Clamp before calling: limit = Math.min(8, Math.max(1, Math.floor(Number(raw)))) and omit the key if NaN.
- Omit query.limit to use the default of 6 when no specific size is needed.
- Validate Number.isInteger(limit) && limit >= 1 && limit <= DASHBOARD_PANEL_CATALOG_MAX_LIMIT before the call, importing the exported constants.
- Catch DashboardPanelCatalogError with reason 'invalid_limit' and retry with the default limit.
Example fix
// before
listDashboardPanelCatalog(live, { limit: Number(searchParams.get('limit')) }); // may be NaN/0/100
// after
const parsed = Number(searchParams.get('limit'));
const limit = Number.isInteger(parsed) ? Math.min(DASHBOARD_PANEL_CATALOG_MAX_LIMIT, Math.max(1, parsed)) : undefined;
listDashboardPanelCatalog(live, limit === undefined ? {} : { limit }); Defensive patterns
Strategy: validation
Validate before calling
import { DASHBOARD_PANEL_CATALOG_MAX_LIMIT } from '@/services/webmcp-panel-catalog';
const parsed = Number(rawLimit);
const limit = Number.isInteger(parsed) && parsed >= 1
? Math.min(parsed, DASHBOARD_PANEL_CATALOG_MAX_LIMIT)
: undefined; Type guard
function isValidLimit(value: unknown): value is number {
return Number.isInteger(value) && (value as number) >= 1 && (value as number) <= DASHBOARD_PANEL_CATALOG_MAX_LIMIT;
} Try / catch
try {
return listDashboardPanelCatalog(live, { limit, ...query });
} catch (err) {
if (err instanceof DashboardPanelCatalogError && err.reason === 'invalid_limit') {
return listDashboardPanelCatalog(live, { ...query, limit: undefined }); // default limit
}
throw err;
} Prevention
- Clamp and floor any computed page size before passing it (Math.min/max/floor).
- Omit limit to accept the default (6) instead of computing your own page size.
- Coerce querystring values with Number() and reject NaN/strings before calling.
- Import DASHBOARD_PANEL_CATALOG_MAX_LIMIT rather than hardcoding 8 so bounds stay in sync.
When it happens
Trigger: Calling with { limit: 0 }, { limit: 50 }, { limit: 6.5 }, { limit: '6' }, { limit: NaN } — any non-integer or out-of-range value, e.g. an unclamped UI page-size selector or string page-size from a querystring.
Common situations: Assuming the server clamps instead of throws; passing string '6' from URL params; float results from dividing available height by row height; request sizes above 8 rejected while tuning output budgets.
Related errors
AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01).
Data as JSON: /api/errors/e1ff567c44f722e8.
Report an issue: GitHub.