thedotmack/claude-mem · error
Invalid operation
Error message
Invalid operation
What it means
GET /api/instructions validates the operation query parameter against the ALLOWED_OPERATIONS allow-list; a value outside the list returns 400 'Invalid operation'. The topic check runs first, so a bad topic masks a bad operation with 'Invalid topic'.
Source
Thrown at src/services/server/Server.ts:298
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' });
}
const sectionText = this.extractInstructionSection(cachedSkillMd, topic);
res.json({ content: [{ type: 'text', text: sectionText }] });
});View on GitHub (pinned to 8bc631a71a)
Solutions
- Use an operation name from ALLOWED_OPERATIONS exactly
- If you want topical content rather than an operation, use ?topic= instead
- Inspect ALLOWED_OPERATIONS in the server source for the current list
Example fix
// before
fetch(`${base}/api/instructions?operation=summarize-all`); // 400 Invalid operation
// after
fetch(`${base}/api/instructions?operation=summarize`); // 200 Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED_OPERATIONS = new Set([/* mirror ALLOWED_OPERATIONS from the server */ 'summarize', 'recall']);
function operationUrl(base: string, operation: string): string | null {
if (!ALLOWED_OPERATIONS.has(operation)) return null; // skip the call entirely
return `${base}/api/instructions?operation=${encodeURIComponent(operation)}`;
} 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?operation=${op}`);
if (res.status === 400) {
const body = await res.json().catch(() => ({}));
if (body.error === 'Invalid operation') throw new Error(`operation "${op}" not supported by this server version`);
if (body.error === 'Invalid topic') throw new Error('topic param is also wrong — fix it first');
throw new Error(`unexpected 400: ${JSON.stringify(body)}`);
} Prevention
- Verify operation names against ALLOWED_OPERATIONS for your server version
- Do not confuse ?topic= and ?operation= — they validate against different lists
- Feature-detect operations at startup rather than assuming availability
When it happens
Trigger: GET /api/instructions?operation=<value> where value is not an allowed operation name — invented names, typos, or operations added/removed in a different server version.
Common situations: Tooling hardcoding operation names that drift across releases; mixing up topic and operation parameters; copied URLs from docs for a different version.
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/25d0bf1d7e229881.
Report an issue: GitHub.