abhigyanpatwari/GitNexus · error

"path" must be a string

Error message

"path" must be a string

What it means

HTTP 400 returned by POST /api/analyze when the JSON body contains a "path" field whose value is not a string. The route destructures { url, path, force, embeddings, dropEmbeddings, token } from req.body and type-checks each optional field before creating a job, because the path value flows straight into the analysis worker as a filesystem location.

Source

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

    requireTrustedOrigin,
    async (req, res) => {
      try {
        const {
          url: repoUrl,
          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

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Send path as one JSON string, e.g. {"path": "/home/me/repos/foo"}
  2. Pick the string out of structured picker results (entries[0].fullPath), not the array or object
  3. Omit the key when there is no local path rather than sending null
  4. Double-check the Content-Type is application/json so the body is actually parsed

Example fix

// before
const body = { path: dirPicker.entries }; // array of picked entries

// after
const body = { path: dirPicker.entries[0].fullPath }; // single absolute path string
Defensive patterns

Strategy: validation

Validate before calling

// Run before POSTing to /api/analyze
if ('path' in body && typeof body.path !== 'string') {
  throw new TypeError(`"path" must be a string, got ${typeof body.path}`);
}

Type guard

const isMaybeString = (v: unknown): v is string | undefined =>
  v === undefined || typeof v === 'string';

Try / catch

On 400, inspect res.body.error — a type failure is deterministic per payload; correct the field (or omit it) before re-sending.

Prevention

When it happens

Trigger: POST /api/analyze with {"path": null}, {"path": 42}, {"path": ["/repos/foo"]} or {"path": {"dir": "/repos/foo"}} — e.g. a directory picker returning an entries array, or a whole config object being sent where one of its string fields was intended.

Common situations: Browser/Electron folder pickers returning entry lists; YAML/env configs parsed into objects; serializers emitting null for undefined; URLSearchParams-style encoders producing arrays for scalar fields.

Related errors


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