abhigyanpatwari/GitNexus · error
Analysis already in progress (job ${job.id})
Error message
Analysis already in progress (job ${job.id}) What it means
JobManager.createJob enforces a single analysis slot. It first dedups: an active job for the same repoUrl or repoPath is returned instead of throwing. Only when a DIFFERENT repo has a non-terminal job (queued/cloning/analyzing) does it throw this error, guarding the one-analysis-at-a-time invariant of POST /api/analyze.
Source
Thrown at gitnexus/src/server/analyze-job.ts:114
/** Create a new job, or return existing active job for the same repo. */
createJob(params: { repoUrl?: string; repoPath?: string }): AnalyzeJob {
// Dedup: return existing active job for the same repo (by URL or path)
for (const job of this.jobs.values()) {
if (!this.isTerminal(job.status)) {
const isSameRepo =
(params.repoUrl && job.repoUrl === params.repoUrl) ||
(params.repoPath && job.repoPath === params.repoPath);
if (isSameRepo) {
return job;
}
}
}
// Single-slot: reject if another job is active (different repo)
for (const job of this.jobs.values()) {
if (!this.isTerminal(job.status)) {
throw new Error(`Analysis already in progress (job ${job.id})`);
}
}
const job: AnalyzeJob = {
id: randomUUID(),
status: 'queued',
repoUrl: params.repoUrl,
repoPath: params.repoPath,
progress: { phase: 'queued', percent: 0, message: 'Waiting to start...' },
startedAt: Date.now(),
retryCount: 0,
};
this.jobs.set(job.id, job);
return job;
}
getJob(id: string): AnalyzeJob | undefined {View on GitHub (pinned to aac7515d2a)
Solutions
- Poll the existing job (GET status endpoint) until it reaches a terminal status, then retry the request
- Cancel the active job via the cancel endpoint if it is stale or unwanted
- Serialize analyze calls in your orchestration so only one is in flight
- If a job is wedged non-terminal with no worker alive, restart the gitnexus server to clear the in-memory map
Example fix
// before
await fetch('/api/analyze', { method: 'POST', body: JSON.stringify({ url: repoB }) }); // 500: already in progress
// after
await waitForTerminalJob(activeJobId); // poll status until succeeded/failed
await fetch('/api/analyze', { method: 'POST', body: JSON.stringify({ url: repoB }) }); Defensive patterns
Strategy: retry
Validate before calling
async function noActiveJob(getStatus) {
const s = await getStatus(); // e.g. GET /api/analyze/status/:id or jobs listing
return !s || ['succeeded', 'failed', 'cancelled'].includes(s.status);
} Type guard
function isTerminalJobStatus(status) {
return ['succeeded', 'failed', 'cancelled'].includes(status);
} Try / catch
async function createJobWithRetry(createJob, p, { pollMs = 2000, maxMs = 30 * 60 * 1000 } = {}) {
for (;;) {
try { return createJob(p); }
catch (e) {
if (!/already in progress/.test(String(e.message))) throw e;
const m = e.message.match(/job (\S+\))/); // active job id
await waitForTerminal(m && m[1], { pollMs, maxMs }); // poll status until terminal
}
}
} Prevention
- Serialize analyze requests in orchestrators — one in flight at a time
- Check job status before creating a new one; expose the active job in the UI so users see why a 409 happened
- Always cancel jobs you abandon, so the single slot is released
- Monitor for jobs stuck non-terminal and restart the server to clear the in-memory map
When it happens
Trigger: POST /api/analyze with url/path for repo B while repo A's job is in any non-terminal status; the in-memory this.jobs map has no terminal job when the request arrives.
Common situations: A UI letting a user queue a second repo while the first analyzes; automation firing parallel analyze requests; a wedged worker whose job never reaches succeeded/failed, permanently holding the slot until server restart (jobs are in-memory).
Related errors
- Analysis already in progress (job ${job.id})
- Analysis already in progress (job ${job.id})
- GitNexus: unable to acquire init lock after ${INIT_LOCK_MAX_
- LadybugDB unavailable for ${repoId}. Another process may be
- Could not allocate an upload directory after ${MAX_NAME_COLL
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/b8c77b7f0c86292d.
Report an issue: GitHub.