{"record":{"id":"4dfd35b4946b20d6","repo":"ruvnet/RuView","slug":"unsupported-guidance-topic-topic-4dfd35","errorCode":null,"errorMessage":"unsupported guidance topic: ${topic}","messagePattern":"unsupported guidance topic: (.+?)","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"harness/ruview/src/guidance.js","lineNumber":361,"sourceCode":"  }\n  if (!options || typeof options !== 'object' || Array.isArray(options)) {\n    throw new TypeError('guidance options must be an object');\n  }\n  if (input.topic !== undefined && typeof input.topic !== 'string') {\n    throw new TypeError('guidance topic must be a string');\n  }\n  if (input.query !== undefined && typeof input.query !== 'string') {\n    throw new TypeError('guidance query must be a string');\n  }\n  if (input.limit !== undefined && (typeof input.limit !== 'number' || !Number.isFinite(input.limit))) {\n    throw new TypeError('guidance limit must be a finite number');\n  }\n  if (options.repoRoot !== undefined && options.repoRoot !== null && typeof options.repoRoot !== 'string') {\n    throw new TypeError('guidance repoRoot must be a string or null');\n  }\n  const topic = input.topic === undefined ? 'overview' : input.topic;\n  if (!GUIDANCE_TOPICS.includes(topic)) {\n    throw new RangeError(`unsupported guidance topic: ${topic}`);\n  }\n  const query = input.query === undefined ? '' : input.query.trim();\n  if (query && (query.length < 2 || query.length > 500)) {\n    throw new RangeError('guidance query must contain 2..500 characters');\n  }\n  const rawLimit = input.limit === undefined ? 20 : input.limit;\n  if (!Number.isFinite(rawLimit) || rawLimit < 1 || rawLimit > 20) {\n    throw new RangeError('guidance limit must be between 1 and 20');\n  }\n  const limit = Math.floor(rawLimit);\n  const wanted = tokenize(query);\n  const candidates = CAPABILITIES\n    .filter((capability) => topic === 'overview' || capability.topics.includes(topic))\n    .map((capability, order) => ({ capability, order, score: scoreCapability(capability, wanted) }))\n    .filter(({ score }) => score > 0)\n    .sort((a, b) => b.score - a.score || a.order - b.order)\n    .slice(0, limit)\n    .map(({ capability }) => ({","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/harness/ruview/src/guidance.js#L343-L379","documentation":"getGuidance validates input.topic against the frozen GUIDANCE_TOPICS allowlist (guidance.js:12): overview, architecture, sensing, hardware, training, homecore, integrations, deployment, community, testing. Matching is exact and case-sensitive; anything else throws this RangeError with the offending topic embedded.","triggerScenarios":"getGuidance({ topic: 'plugins' }) (a homecore-harness topic, not a ruview topic), { topic: 'home core' }, { topic: 'Overview' } (capital O), { topic: 'restore' }, or a typo like 'comunity'.","commonSituations":"Confusing the ruview guidance topics with homecore guidance topics (plugins/restore are homecore); copying a topic from one harness CLI to the other; casing changes after a rename.","solutions":["Use one of the exact allowlisted topics; for the Homecore metaharness questions like plugins/restore use topic 'homecore' with a query.","Import and check the list before calling: import { GUIDANCE_TOPICS } from the guidance module; if (!GUIDANCE_TOPICS.includes(topic)) topic = 'overview';","Lowercase and trim caller input before validation: topic: String(raw).trim().toLowerCase()."],"exampleFix":"// before\ngetGuidance({ topic: 'plugins' }) // RangeError: unsupported guidance topic: plugins\n// after\nimport { GUIDANCE_TOPICS } from './src/guidance.js';\nconst topic = GUIDANCE_TOPICS.includes(rawTopic) ? rawTopic : 'overview';\ngetGuidance({ topic });","handlingStrategy":"validation","validationCode":"import { GUIDANCE_TOPICS } from '@ruvnet/ruview/src/guidance.js';\nconst topic = String(rawTopic ?? 'overview').trim().toLowerCase();\nif (!GUIDANCE_TOPICS.includes(topic)) {\n  throw new Error(`unsupported topic '${topic}'; valid: ${GUIDANCE_TOPICS.join(', ')}`);\n}\ngetGuidance({ topic });","typeGuard":"import { GUIDANCE_TOPICS } from '@ruvnet/ruview/src/guidance.js';\nfunction isGuidanceTopic(v) {\n  return typeof v === 'string' && GUIDANCE_TOPICS.includes(v);\n}","tryCatchPattern":"try {\n  getGuidance({ topic });\n} catch (e) {\n  if (e instanceof RangeError && e.message.startsWith('unsupported guidance topic')) {\n    return getGuidance({ topic: 'overview' }); // sensible fallback topic\n  }\n  throw e;\n}","preventionTips":["Import GUIDANCE_TOPICS and drive your CLI's --topic choices from it so the list can never drift.","Normalize casing and whitespace before validation.","Remember 'plugins'/'restore' are homecore topics; use topic 'homecore' with a query in the ruview harness."],"tags":["validation","guidance","rangeerror","allowlist","ruview-harness"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}