thedotmack/claude-mem · error

NotFound

NotFound

Error message

Project not found

What it means

GET /v1/projects/:id loads the project via ProjectsRepository.getById(id); a null return yields 404 NotFound 'Project not found'. The 404 fires only after ensureProjectAllowed passes, so even a correctly-scoped key gets 404 when the row is unknown or was deleted.

Source

Thrown at src/server/routes/v1/ServerV1Routes.ts:110

      this.audit(req, 'projects.list');
    });

    app.post('/v1/projects', writeAuth, this.handleCreate(CreateProjectSchema, (req, res, body) => {
      if (req.authContext?.projectId) {
        res.status(403).json({ error: 'Forbidden', message: 'Project-scoped API keys cannot create projects' });
        return;
      }
      const project = new ProjectsRepository(this.options.getDatabase()).create(body);
      this.audit(req, 'project.create', project.id);
      res.status(201).json({ project });
    }));

    app.get('/v1/projects/:id', readAuth, (req, res) => {
      const id = this.routeParam(req.params.id);
      if (!this.ensureProjectAllowed(req, res, id)) return;
      const project = new ProjectsRepository(this.options.getDatabase()).getById(id);
      if (!project) {
        res.status(404).json({ error: 'NotFound', message: 'Project not found' });
        return;
      }
      this.audit(req, 'project.read', project.id);
      res.json({ project });
    });

    app.post('/v1/sessions/start', writeAuth, this.handleCreate(CreateServerSessionSchema, (req, res, body) => {
      if (!this.ensureProjectAllowed(req, res, body.projectId)) return;
      const session = new ServerSessionsRepository(this.options.getDatabase()).create(body);
      this.audit(req, 'session.start', session.id, session.projectId);
      res.status(201).json({ session });
    }));

    app.post('/v1/sessions/:id/end', writeAuth, (req, res) => {
      const id = this.routeParam(req.params.id);
      const repo = new ServerSessionsRepository(this.options.getDatabase());
      const existing = repo.getById(id);
      if (!existing) {

View on GitHub (pinned to e2d1df569a)

Solutions

  1. List projects with GET /v1/projects and copy a current id (project-scoped keys see only their own project)
  2. Verify the client points at the server/database where the project lives
  3. Treat 404 as terminal for that id: re-list and use a fresh one instead of retrying
Defensive patterns

Strategy: validation

Validate before calling

async function getProjectOrFail(base: string, key: string, id: string) {
  const res = await fetch(`${base}/v1/projects/${encodeURIComponent(id)}`, { headers: { Authorization: `Bearer ${key}` } });
  if (res.status === 404) {
    const { projects } = await (await fetch(`${base}/v1/projects`, { headers: { Authorization: `Bearer ${key}` } })).json();
    throw new Error(`project ${id} not found; available: ${projects.map((p: { id: string }) => p.id).join(', ')}`);
  }
  return res.json();
}

Type guard

function isNotFoundResponse(status: number, body: unknown): body is { error: 'NotFound'; message: string } {
  return status === 404 && typeof body === 'object' && body !== null && (body as { error?: string }).error === 'NotFound';
}

Try / catch

const res = await fetch(url, { headers });
const body = await res.json().catch(() => ({}));
if (isNotFoundResponse(res.status, body)) {
  // terminal: drop cached id, re-list projects, do not retry the same id
  cache.delete(id);
  return null;
}

Prevention

When it happens

Trigger: GET /v1/projects/<id> where the id does not exist: typo in the URL, a stale id from another environment's database, or a project deleted between listing and fetching.

Common situations: Environment drift (staging ids used against prod); hardcoded project ids in scripts; a project concurrently deleted by another client.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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