thedotmack/claude-mem · error

Invalid topic

Error message

Invalid topic

What it means

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').

Source

Thrown at src/services/server/Server.ts:294

        });
      } else {
        res.status(503).json({
          status: 'initializing',
          message: 'Worker is still initializing, please retry',
        });
      }
    });

    this.app.get('/api/version', (_req: Request, res: Response) => {
      res.status(200).json({ version: BUILT_IN_VERSION });
    });

    this.app.get('/api/instructions', (req: Request, res: Response) => {
      const topic = (req.query.topic as string) || 'all';
      const operation = req.query.operation as string | undefined;

      if (topic && !ALLOWED_TOPICS.includes(topic)) {
        return res.status(400).json({ error: 'Invalid topic' });
      }

      if (operation && !ALLOWED_OPERATIONS.includes(operation)) {
        return res.status(400).json({ error: 'Invalid operation' });
      }

      if (operation) {
        const cached = cachedOperationContent.get(operation);
        if (cached === undefined) {
          logger.debug('HTTP', 'Instruction file not cached at boot', { operation });
          return res.status(404).json({ error: 'Instruction not found' });
        }
        return res.json({ content: [{ type: 'text', text: cached }] });
      }

      if (cachedSkillMd === null) {
        logger.debug('HTTP', 'SKILL.md not cached at boot', { topic });
        return res.status(404).json({ error: 'Instruction not found' });

View on GitHub (pinned to 8bc631a71a)

Solutions

  1. Omit ?topic to receive the full SKILL.md content
  2. Use an allowed topic name exactly as the server defines it
  3. Check ALLOWED_TOPICS in the server source for the current set of values

Example fix

// before
fetch(`${base}/api/instructions?topic=memoriez`); // 400 Invalid topic

// after
fetch(`${base}/api/instructions?topic=memory`); // 200
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED_TOPICS = new Set(['all', /* mirror the server's list */ 'memory', 'sessions', 'projects']);

function instructionsUrl(base: string, topic?: string): string {
  if (topic && !ALLOWED_TOPICS.has(topic)) {
    console.warn(`unknown topic ${topic}; falling back to full SKILL.md`);
    return `${base}/api/instructions`;
  }
  return topic ? `${base}/api/instructions?topic=${encodeURIComponent(topic)}` : `${base}/api/instructions`;
}

Type guard

function isInvalidParameter(status: number, body: unknown, field: 'topic' | 'operation'): body is { error: string } {
  return status === 400 && typeof body === 'object' && body !== null && (body as { error?: string }).error === `Invalid ${field}`;
}

Try / catch

const res = await fetch(`${base}/api/instructions?topic=${topic}`);
if (res.status === 400) {
  const body = await res.json().catch(() => ({}));
  if (body.error === 'Invalid topic') return fetch(`${base}/api/instructions`).then(r => r.json()); // fall back to full content
  throw new Error(`instructions request rejected: ${JSON.stringify(body)}`);
}

Prevention

When it happens

Trigger: 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.

Common situations: Prompt templates or agents referencing topic names from an older release; passing an operation name into the topic param; case-sensitive topic strings.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-08-20). Data as JSON: /api/errors/a1f666a3829ddfcf. Report an issue: GitHub.