abhigyanpatwari/GitNexus · error

Failed to start analysis

Error message

Failed to start analysis

What it means

HTTP 500 returned by POST /api/analyze's outer catch when the synchronous part of the route throws anything other than an 'already in progress' conflict. The response forwards err.message when present and falls back to this literal string only when the error has no message — so seeing the exact text 'Failed to start analysis' means an anonymous/unexpected throw; the underlying error is available in the serve logs.

Source

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

              throw new Error('No target path resolved');
            }

            launchAnalysisWorker(job, targetPath, { force, embeddings, dropEmbeddings });
          } catch (err: any) {
            if (targetPath) releaseRepoLock(getStoragePath(targetPath));
            jobManager.updateJob(job.id, {
              status: 'failed',
              error: err.message || 'Analysis failed',
            });
          }
        })();

        res.status(202).json({ jobId: job.id, status: job.status });
      } catch (err: any) {
        if (err.message?.includes('already in progress')) {
          res.status(409).json({ error: err.message });
        } else {
          res.status(500).json({ error: err.message || 'Failed to start analysis' });
        }
      }
    },
  );

  // POST /api/analyze/upload — analyze a browser folder upload.
  // Securely ingests the multipart upload into a sandbox, promotes it to a
  // persistent dir, and analyzes it via the shared job/worker machinery.
  // localhost-only (no cross-origin write reach) + conservative rate limit.
  app.post(
    '/api/analyze/upload',
    createRouteLimiter({ limit: 5 }),
    requireTrustedOrigin,
    createAnalyzeUploadHandler({
      createJob: (params) => jobManager.createJob(params),
      launch: (job, targetPath, opts) => launchAnalysisWorker(job, targetPath, opts),
      failJob: (jobId, error) => jobManager.updateJob(jobId, { status: 'failed', error }),
    }),

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Check the serve process output — the route and the global handler log the real error; the 500 body is intentionally vague
  2. Reproduce with the exact body: any non-empty err.message replaces the literal text, which narrows the cause
  3. Retry once after confirming no job is stuck (a stuck non-terminal job surfaces as 409 and can masquerade as 'cannot start')
  4. If reproducible, update GitNexus and report the stack — a 500 here is by definition a server-side defect

Example fix

// before
const { jobId } = await res.json(); // opaque failure on 500

// after
if (res.status === 409) { /* adopt/poll the active job, see error 344 */ }
else if (res.status >= 500) { await backoffRetry(() => postAnalyze(body), 2); }
else if (!res.ok) throw new Error((await res.json()).error);
Defensive patterns

Strategy: retry

Try / catch

Branch on status at the fetch boundary: 409 → adopt/poll the active job; 5xx → retry the idempotent POST with exponential backoff (2-3 attempts); other 4xx → surface the forwarded error text to the caller.

Prevention

When it happens

Trigger: An unexpected exception inside job creation or route setup (corrupted internal state, memory pressure, a GitNexus bug); an error object with an empty .message reaching the catch; anything the route's finer-grained 400 validations did not anticipate.

Common situations: Version skew between client expectations and an older serve build; disk-full or permission-broken storage making setup calls throw; rare post-upgrade bugs — the literal fallback text is the tell that message context was lost.

Related errors


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