abhigyanpatwari/GitNexus · warning
Batch enrichment failed, falling back to heuristics:
Error message
Batch enrichment failed, falling back to heuristics:
What it means
Batch enrichment sends up to `batchSize` (default 5) cluster descriptions in one LLM prompt and expects a JSON array back. The whole batch — generate() call plus the regex extract and JSON.parse of the array — sits in one try/catch: any failure logs 'Batch enrichment failed, falling back to heuristics' and every community in that batch drops to its heuristicLabel. Unlike the single-cluster path, a malformed batch response (prose instead of JSON, truncated array, context-window overflow) also triggers this warning because JSON.parse happens inside the try.
Source
Thrown at gitnexus/src/core/ingestion/cluster-enricher.ts:217
const jsonMatch = response.match(/\[[\s\S]*\]/);
if (jsonMatch) {
const parsed = JSON.parse(jsonMatch[0]) as Array<{
id: string;
name: string;
keywords: string[];
description: string;
}>;
for (const item of parsed) {
enrichments.set(item.id, {
name: item.name,
keywords: item.keywords || [],
description: item.description || '',
});
}
}
} catch (error) {
logger.warn({ error }, 'Batch enrichment failed, falling back to heuristics:');
// Fallback for this batch
for (const community of batch) {
enrichments.set(community.id, {
name: community.heuristicLabel,
keywords: [],
description: '',
});
}
}
}
// Fill in any missing communities
for (const community of communities) {
if (!enrichments.has(community.id)) {
enrichments.set(community.id, {
name: community.heuristicLabel,
keywords: [],
description: '',View on GitHub (pinned to aac7515d2a)
Solutions
- Inspect the logged { error } field to distinguish API failure (401/429/ETIMEDOUT) from SyntaxError (malformed model output)
- For SyntaxError/truncation: lower batchSize (fewer clusters per prompt) so responses fit and stay well-formed
- For API errors: fix credentials/endpoint or retry after the rate-limit window
- Re-run enrichment — missing entries are backfilled with heuristics automatically
Example fix
// before: one bad item or a truncated array fails the whole batch
const parsed = JSON.parse(jsonMatch[0]) as Item[];
for (const item of parsed) enrichments.set(item.id, item);
// after: validate per item, salvage the good ones
for (const raw of parsed) {
if (raw && typeof raw.id === 'string' && typeof raw.name === 'string') {
enrichments.set(raw.id, { name: raw.name, keywords: Array.isArray(raw.keywords) ? raw.keywords : [], description: typeof raw.description === 'string' ? raw.description : '' });
} // else: this id alone falls back to heuristic, batch survives
} Defensive patterns
Strategy: retry
Validate before calling
// before each batch: cheap reachability probe; on failure retry once, then shrink the batch
const ok = await llmClient.generate('ping').then(() => true).catch(() => false);
if (!ok) await backoffThenRetry(batch, /* smallerSize */ Math.max(1, batchSize - 2)); Try / catch
try {
const parsed = JSON.parse(response.match(/\[[\s\S]*\]/)[0]) as Item[];
for (const raw of parsed) {
if (raw && typeof raw.id === 'string') enrichments.set(raw.id, normalizeItem(raw)); // per-item guard
}
} catch (error) {
for (const community of batch) enrichments.set(community.id, heuristicFor(community)); // batch-level fallback
} Prevention
- Keep batchSize small enough that 5 clusters x 15 members stays well inside the model context window
- Ask for raw JSON output (no markdown fences) and validate per item so one bad entry does not sink the batch
- Retry transient 429/5xx batches; heuristics only after a retry fails
- Diff batch responses against the expected [{id, name, keywords, description}] shape in tests
When it happens
Trigger: llmClient.generate rejecting (auth/network/rate limit), or the model returning a response whose array extraction fails: JSON.parse throwing on truncated output, the /\[[\s\S]*\]/ greedy match capturing invalid text, or a batch prompt exceeding the model context so the reply is cut off mid-array.
Common situations: Large repos where 5 clusters x 15 members produces prompts near the context limit; models that wrap answers in prose despite the 'Output JSON array' instruction; rate limits and provider outages affecting a whole batch at once.
Related errors
- Failed to enrich cluster ${community.id}:
- Embedding endpoint returned ${received} vectors for ${expect
- --allow-insecure-connection / GITNEXUS_ALLOW_INSECURE_CONNEC
- Invalid LLM base URL: must be a well-formed http:// or https
- LLM base URL must use http:// or https:// (got ${parsed.prot
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/0a141ac2407bf1ea.
Report an issue: GitHub.