thedotmack/claude-mem · error
Corpus "${name}" not found
Error message
Corpus "${name}" not found What it means
HTTP 404 from CorpusRoutes.corpusNotFound, returned by every /api/corpus/:name handler (GET, DELETE, rebuild, prime, query, reprime) when the named corpus is not in the in-memory corpus store. The body is richer than a plain 404: it includes a fix hint and an available array listing corpora that do exist, so the correct name is one field away.
Source
Thrown at src/services/worker/http/routes/CorpusRoutes.ts:84
private corpusBuilder: CorpusBuilder,
private knowledgeAgent: KnowledgeAgent
) {
super();
}
setupRoutes(app: express.Application): void {
app.post('/api/corpus', validateBody(buildCorpusSchema), this.handleBuildCorpus.bind(this));
app.get('/api/corpus', this.handleListCorpora.bind(this));
app.get('/api/corpus/:name', this.handleGetCorpus.bind(this));
app.delete('/api/corpus/:name', this.handleDeleteCorpus.bind(this));
app.post('/api/corpus/:name/rebuild', this.handleRebuildCorpus.bind(this));
app.post('/api/corpus/:name/prime', this.handlePrimeCorpus.bind(this));
app.post('/api/corpus/:name/query', validateBody(queryCorpusSchema), this.handleQueryCorpus.bind(this));
app.post('/api/corpus/:name/reprime', this.handleReprimeCorpus.bind(this));
}
private corpusNotFound(res: Response, name: string): void {
res.status(404).json({
error: `Corpus "${name}" not found`,
fix: 'Check the corpus name or build a new one',
available: this.corpusStore.list().map(c => c.name)
});
}
private handleBuildCorpus = this.wrapHandler(async (req: Request, res: Response): Promise<void> => {
const { name, description, project, types, concepts, files, query, date_start, date_end, limit } =
req.body as z.infer<typeof buildCorpusSchema>;
const filter: CorpusFilter = {};
if (project) filter.project = project;
if (types && types.length > 0) filter.types = types as CorpusFilter['types'];
if (concepts && concepts.length > 0) filter.concepts = concepts;
if (files && files.length > 0) filter.files = files;
if (query) filter.query = query;
if (date_start) filter.date_start = date_start;
if (date_end) filter.date_end = date_end;View on GitHub (pinned to e2d1df569a)
Solutions
- Read the available array in the 404 body and use one of those exact names
- If none exist, build one first: POST /api/corpus with the desired filter (project, concepts, files, date range)
- Check for case/exact-match differences — lookup is by exact name string
Example fix
// before
const r = await fetch(`${base}/api/corpus/Default/query`, { method: 'POST', body: JSON.stringify({ q: 'hooks' }) });
// 404: available: ["default-project"]
// after
const r = await fetch(`${base}/api/corpus/default-project/query`, { method: 'POST', body: JSON.stringify({ q: 'hooks' }) }); Defensive patterns
Strategy: validation
Validate before calling
async function firstAvailableCorpus(base: string, fallback?: string): Promise<string | undefined> {
const list = await (await fetch(`${base}/api/corpus`)).json();
const names: string[] = (list.corpora ?? []).map((c: { name: string }) => c.name);
return names.includes(fallback ?? '') ? fallback : names[0];
} Type guard
interface CorpusNotFoundBody {
error: string;
fix: string;
available: string[];
}
function isCorpusNotFound(body: unknown, status: number): body is CorpusNotFoundBody {
return status === 404 && Array.isArray((body as { available?: unknown })?.available);
} Try / catch
const res = await callApi();
if (res.status === 404) {
const body = await res.json();
if (isCorpusNotFound(body, res.status))
return retryWith(body.available[0]); // self-heal using the provided list
throw new Error('corpus route failed');
} Prevention
- Discover corpus names at runtime via GET /api/corpus instead of hardcoding them
- After a fresh install, build a corpus before any query/rebuild/prime call
- Use exact names (case-sensitive) — copy from the available array
When it happens
Trigger: Querying or rebuilding a corpus name that was never built, was deleted, or whose build failed earlier; case mismatches in the name; using an id instead of the human name.
Common situations: Prompts or scripts hardcoding a corpus name like 'default' after the user renamed or removed it; querying right after a fresh install where no corpus exists yet; a build that appeared to succeed but actually errored.
Related errors
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/853fd942f566da55.
Report an issue: GitHub.