abhigyanpatwari/GitNexus · error

"url" must be a string

Error message

"url" must be a string

What it means

HTTP 400 returned by POST /api/analyze when the JSON body contains a "url" field whose value is not a JavaScript string (number, boolean, object, array, or null all qualify). GitNexus validates the analyze inputs at the route boundary because the URL is handed directly to the git clone machinery, which requires a string. This is a client contract violation detected before any job is created.

Source

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

  // POST /api/analyze — start a new analysis job
  app.post(
    '/api/analyze',
    createRouteLimiter({ limit: 10 }),
    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;

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Send url as a single JSON string: {"url":"https://github.com/org/repo"} with Content-Type: application/json
  2. Stringify URL objects before sending: use url.toString() or url.href
  3. Omit the key instead of sending "url": null — undefined counts as absent, null is a type error
  4. For local directories send "path" (an absolute path string) instead of "url"

Example fix

// before
const body = { url: new URL('https://github.com/org/repo') }; // object, not string
await fetch('/api/analyze', { method: 'POST', body: JSON.stringify(body) });

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

Strategy: validation

Validate before calling

// Run before POSTing to /api/analyze
const assertAnalyzeBody = (b: Record<string, unknown>) => {
  if (b.url !== undefined && typeof b.url !== 'string')
    throw new TypeError(`"url" must be a string, got ${typeof b.url}`);
  if (b.path !== undefined && typeof b.path !== 'string')
    throw new TypeError(`"path" must be a string, got ${typeof b.path}`);
};

Type guard

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

Try / catch

On a 400 response read { error } from the JSON body and fix the payload — this error is permanent for that request, so never blind-retry the identical body.

Prevention

When it happens

Trigger: POST /api/analyze with Content-Type: application/json and a body like {"url": 123}, {"url": null}, {"url": ["https://github.com/org/repo"]} or {"url": {"href": "..."}}. Typical producers: forgetting .toString() on a WHATWG URL object, a form/query-string serializer wrapping scalar fields in arrays, or undefined being serialized as null.

Common situations: A web UI passing a parsed URL object instead of its href; a client refactor switching to query-string-style bodies (?url=...) that a serializer turns into arrays; sending a numeric repository id; JSON libraries that emit explicit nulls for absent values.

Related errors


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