{"record":{"id":"a1f666a3829ddfcf","repo":"thedotmack/claude-mem","slug":"invalid-topic","errorCode":null,"errorMessage":"Invalid topic","messagePattern":"Invalid topic","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"src/services/server/Server.ts","lineNumber":294,"sourceCode":"        });\n      } else {\n        res.status(503).json({\n          status: 'initializing',\n          message: 'Worker is still initializing, please retry',\n        });\n      }\n    });\n\n    this.app.get('/api/version', (_req: Request, res: Response) => {\n      res.status(200).json({ version: BUILT_IN_VERSION });\n    });\n\n    this.app.get('/api/instructions', (req: Request, res: Response) => {\n      const topic = (req.query.topic as string) || 'all';\n      const operation = req.query.operation as string | undefined;\n\n      if (topic && !ALLOWED_TOPICS.includes(topic)) {\n        return res.status(400).json({ error: 'Invalid topic' });\n      }\n\n      if (operation && !ALLOWED_OPERATIONS.includes(operation)) {\n        return res.status(400).json({ error: 'Invalid operation' });\n      }\n\n      if (operation) {\n        const cached = cachedOperationContent.get(operation);\n        if (cached === undefined) {\n          logger.debug('HTTP', 'Instruction file not cached at boot', { operation });\n          return res.status(404).json({ error: 'Instruction not found' });\n        }\n        return res.json({ content: [{ type: 'text', text: cached }] });\n      }\n\n      if (cachedSkillMd === null) {\n        logger.debug('HTTP', 'SKILL.md not cached at boot', { topic });\n        return res.status(404).json({ error: 'Instruction not found' });","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/8bc631a71a487424b866756e43a6efa4574cc66b/src/services/server/Server.ts#L276-L312","documentation":"GET /api/instructions validates the topic query parameter against the ALLOWED_TOPICS allow-list; any value not in the list returns 400 'Invalid topic' before operation validation or content lookup. Omitting the parameter is fine (defaults to 'all').","triggerScenarios":"GET /api/instructions?topic=<value> where value is not an allowed topic — typo, wrong casing, or a topic name removed/renamed in the current server version.","commonSituations":"Prompt templates or agents referencing topic names from an older release; passing an operation name into the topic param; case-sensitive topic strings.","solutions":["Omit ?topic to receive the full SKILL.md content","Use an allowed topic name exactly as the server defines it","Check ALLOWED_TOPICS in the server source for the current set of values"],"exampleFix":"// before\nfetch(`${base}/api/instructions?topic=memoriez`); // 400 Invalid topic\n\n// after\nfetch(`${base}/api/instructions?topic=memory`); // 200","handlingStrategy":"validation","validationCode":"const ALLOWED_TOPICS = new Set(['all', /* mirror the server's list */ 'memory', 'sessions', 'projects']);\n\nfunction instructionsUrl(base: string, topic?: string): string {\n  if (topic && !ALLOWED_TOPICS.has(topic)) {\n    console.warn(`unknown topic ${topic}; falling back to full SKILL.md`);\n    return `${base}/api/instructions`;\n  }\n  return topic ? `${base}/api/instructions?topic=${encodeURIComponent(topic)}` : `${base}/api/instructions`;\n}","typeGuard":"function isInvalidParameter(status: number, body: unknown, field: 'topic' | 'operation'): body is { error: string } {\n  return status === 400 && typeof body === 'object' && body !== null && (body as { error?: string }).error === `Invalid ${field}`;\n}","tryCatchPattern":"const res = await fetch(`${base}/api/instructions?topic=${topic}`);\nif (res.status === 400) {\n  const body = await res.json().catch(() => ({}));\n  if (body.error === 'Invalid topic') return fetch(`${base}/api/instructions`).then(r => r.json()); // fall back to full content\n  throw new Error(`instructions request rejected: ${JSON.stringify(body)}`);\n}","preventionTips":["Pin topic names in constants reviewed on server upgrades","Default to omitting ?topic — full SKILL.md is always valid","Topics are case-sensitive: match the server's spelling exactly"],"tags":["query-parameters","http-400","instructions"],"backgroundTag":"invalid-query-parameter","analyzedSha":"8bc631a71a487424b866756e43a6efa4574cc66b","analyzedAt":"2026-08-20T23:58:13.836Z","contentChangedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}