{"record":{"id":"2ef72202da49be9d","repo":"koala73/worldmonitor","slug":"invalid-category","errorCode":"invalid_category","errorMessage":"category must be a known panel category key.","messagePattern":"category must be a known panel category key\\.","errorType":"validation","errorClass":"DashboardPanelCatalogError","httpStatus":null,"severity":"error","filePath":"src/services/webmcp-panel-catalog.ts","lineNumber":165,"sourceCode":"\n  const variantFilter = query.variant;\n  if (variantFilter !== undefined) {\n    if (typeof variantFilter !== 'string' || !isSiteVariant(variantFilter)) {\n      throw new DashboardPanelCatalogError(\n        'invalid_variant',\n        'variant must be one of: full, tech, finance, commodity, energy, happy.',\n      );\n    }\n  }\n\n  const categoryFilter = query.category;\n  if (categoryFilter !== undefined) {\n    if (\n      typeof categoryFilter !== 'string'\n      || !CATEGORY_KEY_RE.test(categoryFilter)\n      || !PANEL_CATEGORY_KEY_SET.has(categoryFilter)\n    ) {\n      throw new DashboardPanelCatalogError(\n        'invalid_category',\n        'category must be a known panel category key.',\n      );\n    }\n  }\n\n  if (query.enabled !== undefined && typeof query.enabled !== 'boolean') {\n    throw new DashboardPanelCatalogError(\n      'malformed_arguments',\n      'enabled must be a boolean.',\n    );\n  }\n  if (query.available !== undefined && typeof query.available !== 'boolean') {\n    throw new DashboardPanelCatalogError(\n      'malformed_arguments',\n      'available must be a boolean.',\n    );\n  }","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/koala73/worldmonitor/blob/9361220cc013571781071f0206e4d80fd14b2f7f/src/services/webmcp-panel-catalog.ts#L147-L183","documentation":"listDashboardPanelCatalog() validates query.category against a camelCase-style regex and the set of known panel category keys (PANEL_CATEGORY_MAP keys plus 'other'). An unknown or malformed category string throws DashboardPanelCatalogError with reason 'invalid_category'. The catalog only supports filtering by categories that actually exist in the panel registry.","triggerScenarios":"Calling listDashboardPanelCatalog(live, { category: 'markets' }) where 'markets' is not a key of PANEL_CATEGORY_MAP; categories with uppercase initials, hyphens, or spaces failing CATEGORY_KEY_RE (e.g. 'Market-Data', 'AI tools'); a category key removed/renamed in config/panels.","commonSituations":"Hardcoding a category name from memory instead of importing DASHBOARD_PANEL_CATALOG_CATEGORY_KEYS; an agent guessing a plausible category; categories drifting after PANEL_CATEGORY_MAP was reorganized.","solutions":["Use a category key from DASHBOARD_PANEL_CATALOG_CATEGORY_KEYS (exported from webmcp-panel-catalog.ts) instead of a free-form string.","Validate: typeof category === 'string' && /^[a-z][a-zA-Z0-9]*$/.test(category) && DASHBOARD_PANEL_CATALOG_CATEGORY_KEYS.includes(category) before calling.","Catch DashboardPanelCatalogError with reason 'invalid_category' and fall back to listing without a category filter.","After adding/renaming categories in PANEL_CATEGORY_MAP, update all callers that reference the old key."],"exampleFix":"// before\nlistDashboardPanelCatalog(live, { category: 'markets' });\n// after\nconst category = DASHBOARD_PANEL_CATALOG_CATEGORY_KEYS.includes(requested) ? requested : undefined;\nlistDashboardPanelCatalog(live, category ? { category } : {});","handlingStrategy":"validation","validationCode":"import { DASHBOARD_PANEL_CATALOG_CATEGORY_KEYS } from '@/services/webmcp-panel-catalog';\nconst category = DASHBOARD_PANEL_CATALOG_CATEGORY_KEYS.includes(rawCategory as never)\n  ? rawCategory\n  : undefined;","typeGuard":"function isPanelCategoryKey(value: unknown): value is string {\n  return typeof value === 'string'\n    && /^[a-z][a-zA-Z0-9]*$/.test(value)\n    && DASHBOARD_PANEL_CATALOG_CATEGORY_KEYS.includes(value);\n}","tryCatchPattern":"try {\n  return listDashboardPanelCatalog(live, query);\n} catch (err) {\n  if (err instanceof DashboardPanelCatalogError && err.reason === 'invalid_category') {\n    const { category, ...rest } = query;\n    return listDashboardPanelCatalog(live, rest);\n  }\n  throw err;\n}","preventionTips":["Import category keys from DASHBOARD_PANEL_CATALOG_CATEGORY_KEYS instead of hardcoding strings.","When renaming/adding categories in PANEL_CATEGORY_MAP, grep and update all filter call sites.","Validate both shape (regex) and membership (key set) before passing category filters.","Surface the valid category list to agents/tools in schema descriptions."],"tags":["validation","panel-catalog","category","unknown-identifier"],"backgroundTag":"invalid-enum-value","analyzedSha":"9361220cc013571781071f0206e4d80fd14b2f7f","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}