abhigyanpatwari/GitNexus · error

Provide "url" (git URL) or "path" (local path)

Error message

Provide "url" (git URL) or "path" (local path)

What it means

HTTP 400 returned by POST /api/analyze when the body provides neither "url" nor "path" (the check is falsy-based, so empty strings count as missing too). The route requires exactly one analysis source: a git URL to clone or an absolute local path to index; a body carrying only auxiliary fields (token, force, embeddings, dropEmbeddings) is not enough.

Source

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

          path: repoLocalPath,
          force,
          embeddings,
          dropEmbeddings,
          token: repoToken,
        } = req.body;

        // Input type validation
        if (repoUrl !== undefined && typeof repoUrl !== 'string') {
          res.status(400).json({ error: '"url" must be a string' });
          return;
        }
        if (repoLocalPath !== undefined && typeof repoLocalPath !== 'string') {
          res.status(400).json({ error: '"path" must be a string' });
          return;
        }

        if (!repoUrl && !repoLocalPath) {
          res.status(400).json({ error: 'Provide "url" (git URL) or "path" (local path)' });
          return;
        }

        // Token: optional, restricted charset to prevent header smuggling
        // (CRLF), bound length, and bound to github.com (see validateAnalyzeToken).
        const tokenError = validateAnalyzeToken(repoToken, repoUrl);
        if (tokenError) {
          res.status(tokenError.status).json({ error: tokenError.error });
          return;
        }

        // Path validation. The previous `normalize !== resolve` guard was inert
        // (both collapse `..` identically) and only false-rejected trailing
        // slashes, so it is dropped. Analyzing a local path the operator names
        // is the tool's intended capability (same as the CLI); the dangerous
        // part was cross-origin reach, which is closed by requireTrustedOrigin
        // on this route (scoped to loopback, the server's own bound host, and a
        // configured GITNEXUS_PUBLIC_ORIGIN — other LAN devices are NOT

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Include exactly one of {"url": "<git-url>"} or {"path": "</absolute/path>"} in the JSON body
  2. Set Content-Type: application/json — without it req.body stays empty and every field reads as missing
  3. Check for renamed keys: this route only reads url, path, force, embeddings, dropEmbeddings, token
  4. Smoke-test with curl: curl -X POST http://localhost:4747/api/analyze -H 'Content-Type: application/json' -d '{"url":"https://github.com/org/repo"}'

Example fix

// before
await fetch('/api/analyze', {
  method: 'POST',
  body: JSON.stringify({ repo: 'org/repo' }), // wrong key, no content-type
});

// after
await fetch('/api/analyze', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ url: 'https://github.com/org/repo' }),
});
Defensive patterns

Strategy: validation

Validate before calling

// Exactly one source must be present before sending
const hasSource = (b: Record<string, unknown>) =>
  (typeof b.url === 'string' && b.url !== '') ||
  (typeof b.path === 'string' && b.path !== '');
if (!hasSource(body)) throw new Error('Provide "url" (git URL) or "path" (local path)');

Type guard

const isAnalyzeRequest = (b: unknown): b is { url: string } | { path: string } => {
  if (typeof b !== 'object' || b === null) return false;
  const o = b as Record<string, unknown>;
  return (
    (typeof o.url === 'string' && o.url !== '') ||
    (typeof o.path === 'string' && o.path !== '')
  );
};

Prevention

When it happens

Trigger: POSTing {} or {"token":"..."} or {"force":true}; sending the parameters as a query string (?url=...) or form-data so express.json() never populates req.body; typo'd or renamed keys such as "repo", "uri", "localPath" that this route never reads.

Common situations: Missing Content-Type: application/json header so the JSON body is skipped by the parser; client refactors renaming fields; copy-pasted curl with parameters in the URL instead of -d; contract tests posting an empty object.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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