abhigyanpatwari/GitNexus · error

Repository not found. Run: gitnexus analyze

Error message

Repository not found. Run: gitnexus analyze

What it means

HTTP 404 from GET /api/repo when resolveRepo cannot find the requested repository: either the ?repo= name does not match a registered repo, or no ?repo= was given and the server's default resolution found nothing. The route is rate-limited (60 rpm/IP by default) because resolveRepo canonicalizes the attacker-supplied repo parameter. The remediation message is baked in: the repository must be indexed first with `gitnexus analyze` before the API can serve metadata for it.

Source

Thrown at gitnexus/src/server/api.ts:958

          lastCommit: r.lastCommit,
          stats: r.stats,
        })),
      );
    } catch (err: any) {
      res.status(500).json({ error: err.message || 'Failed to list repos' });
    }
  });

  // Get repo info
  // Rate-limited (CodeQL js/missing-rate-limiting): resolveRepo canonicalizes
  // the attacker-supplied ?repo= param (realpathSync probe for absolute /
  // Windows-shaped claims). Default 60 rpm/IP — web callers hit this route
  // only on connect/switch, never in a polling loop.
  app.get('/api/repo', createRouteLimiter(), async (req, res) => {
    try {
      const entry = await resolveRepo(requestedRepo(req), false, req);
      if (!entry) {
        res.status(404).json({ error: 'Repository not found. Run: gitnexus analyze' });
        return;
      }
      // Timed out waiting for an active analysis job
      if (entry.__timedOut) {
        res.status(503).json({
          error: `Repository analysis for "${entry.repoName}" is taking longer than expected. Please try again in a moment.`,
        });
        return;
      }
      const meta = await loadMeta(entry.storagePath);
      res.json({
        name: entry.name,
        repoPath: entry.path,
        indexedAt: meta?.indexedAt ?? entry.indexedAt,
        stats: meta?.stats ?? entry.stats ?? {},
      });
    } catch (err: any) {
      res.status(500).json({ error: err.message || 'Failed to get repo info' });

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Run `gitnexus analyze` in the repository root, wait for it to register, then retry the request
  2. Discover the exact registered name via GET /api/repos and send ?repo=<that exact name>
  3. If you meant the default repo, start serve from that repo's root directory
  4. For upload-based flows, poll the analysis job until it completes — only then does /api/repo resolve
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the repo is registered before connecting the UI.
const repos = await (await fetch(`${base}/api/repos`)).json();
if (!repos.some((r: { name: string }) => r.name === targetRepo)) {
  throw new Error(`run 'gitnexus analyze' in ${targetRepo} first`);
}

Try / catch

const res = await fetch(`${base}/api/repo?repo=${encodeURIComponent(name)}`);
if (res.status === 404 && /Run: gitnexus analyze/.test((await res.json()).error)) {
  await runAnalyze(name); // or guide the user to
  return fetch(`${base}/api/repo?repo=${encodeURIComponent(name)}`);
}

Prevention

When it happens

Trigger: GET /api/repo?repo=wrong-name where the registered name differs (case, org prefix, .git suffix); starting gitnexus serve in a fresh clone that has never been analyzed; querying after the index storage was wiped; web UI connecting before the first analysis finished registering.

Common situations: New contributor clones the repo, runs serve, opens the web UI, and gets this before their first analyze; name mismatches between what the UI sends and the registry entry; switching serve between multiple repos with stale UI state; CI ephemeral checkouts with cold indexes.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20). Data as JSON: /api/errors/5063248f66c24d6f. Report an issue: GitHub.