Egonex-AI/Understand-Anything · error · Error
Retry endpoint descriptors are missing
Error message
Retry endpoint descriptors are missing
What it means
When `incremental-symbol-retry.json` matches the plan's commit range and contains an `inboundEdgeCandidates` array, it is treated as a valid retry record — which also requires a `currentFiles` array holding the endpoint descriptors for the retry. If `currentFiles` is missing or not an array while the rest looks valid, the retry record is internally incomplete and the validator throws, since inbound edge candidates cannot be resolved without endpoint file descriptors.
Source
Thrown at understand-anything-plugin/skills/understand/validate-incremental-symbols.mjs:386
}
}
const result = compareFileSymbols(previous, current, baseEvidence, headEvidence);
report.files.push(result);
if (result.missing.some(node => node.status !== 'deleted')) report.unresolvedFiles.push(previous.filePath);
}
report.ok = report.errors.length === 0 && report.unresolvedFiles.length === 0;
if (report.ok) {
const retryPath = join(intermediateDir, 'incremental-symbol-retry.json');
const retry = existsSync(retryPath) ? readJson(retryPath) : null;
const candidatePath = join(intermediateDir, 'incremental-edge-candidates.json');
const currentCandidates = existsSync(candidatePath) ? readJson(candidatePath) : null;
if (currentCandidates && (currentCandidates.baseCommit !== plan.baseCommit
|| currentCandidates.headCommit !== plan.headCommit || !Array.isArray(currentCandidates.edges))) {
throw new Error('Current edge candidates do not match the incremental plan');
}
const hasRetry = retry?.baseCommit === plan.baseCommit && retry.headCommit === plan.headCommit
&& Array.isArray(retry.inboundEdgeCandidates);
if (hasRetry && !Array.isArray(retry.currentFiles)) throw new Error('Retry endpoint descriptors are missing');
const candidates = [
...(currentCandidates?.edges ?? []).map(edge => ({ edge, saved: false })),
...(hasRetry ? retry.inboundEdgeCandidates : []).map(edge => ({ edge, saved: true })),
];
if (candidates.length || hasRetry) {
const ids = new Set(graph.nodes.map(node => node.id));
const replacements = new Map(report.files.flatMap(file => file.replacements)
.map(({ oldId, newId }) => [oldId, newId]));
const deleted = new Set(report.files.flatMap(file => file.missing.map(node => node.id)));
const baselineBindings = new Map(baseline.files.flatMap(file => file.nodes.filter(symbolKind))
.map(node => [node.id, deleted.has(node.id) ? null : replacements.get(node.id) ?? node.id]));
const currentBindings = new Map();
// These descriptors belong to the initial CURRENT analysis, not the
// old published graph. Both sides therefore map against HEAD source.
for (const previous of hasRetry ? retry.currentFiles : []) {
const current = fileGraph(previous.filePath);
const needsEvidence = previous.nodes.some(node => symbolKind(node) && !hasPreservedIdentity(node, previous, current, true));
const evidence = needsEvidence && previous.filePath ? await parseHead(previous.filePath) : undefined;View on GitHub (pinned to 07edf82a04)
Solutions
- Delete `incremental-symbol-retry.json` and re-run the step that produces it so both `inboundEdgeCandidates` and `currentFiles` are written atomically.
- Inspect the retry file (`jq 'keys' incremental-symbol-retry.json`) to confirm which fields survived and fix the interrupted writer.
- Make the retry writer emit the file in one atomic write (write temp file + rename) to avoid partial records.
- If a schema rename caused it, align the producer and validator on the `currentFiles` field name.
Example fix
// before: incomplete retry record
{ "baseCommit": "a", "headCommit": "b", "inboundEdgeCandidates": [...] }
// after: regenerate with both fields written atomically
rm .ua/intermediate/incremental-symbol-retry.json
# re-run retry recording => { baseCommit, headCommit, inboundEdgeCandidates: [...], currentFiles: [...] } Defensive patterns
Strategy: validation
Validate before calling
const rPath = join(dir,'incremental-symbol-retry.json');
if (existsSync(rPath)) {
const r = JSON.parse(readFileSync(rPath,'utf8'));
const hasInbound = Array.isArray(r.inboundEdgeCandidates);
if (hasInbound && !Array.isArray(r.currentFiles)) {
unlinkSync(rPath); // incomplete retry record; force regeneration
await rerunRetryRecording();
}
} Type guard
function isCompleteRetryRecord(plan, r) {
return r != null && r.baseCommit === plan.baseCommit
&& r.headCommit === plan.headCommit
&& Array.isArray(r.inboundEdgeCandidates)
&& Array.isArray(r.currentFiles);
} Try / catch
try {
await validateIncrementalSymbols({ projectRoot, intermediateDir });
} catch (err) {
if (err.message === 'Retry endpoint descriptors are missing') {
rmSync(join(intermediateDir, 'incremental-symbol-retry.json'));
await rerunRetryRecording(); // rewrite with currentFiles included
} else throw err;
} Prevention
- Write retry records atomically (temp file + rename) so partial writes never persist.
- Never hand-trim fields (like currentFiles) from intermediate files.
- Keep producer and validator field names in sync.
- Delete the retry file and regenerate whenever validation flags it as incomplete.
When it happens
Trigger: Calling `validateIncrementalSymbols` when `incremental-symbol-retry.json` has matching baseCommit/headCommit and an `inboundEdgeCandidates` array but `currentFiles` is absent, null, or not an array — e.g. a partially written or hand-trimmed retry file.
Common situations: The retry-writing step crashed after writing inboundEdgeCandidates but before currentFiles; the file was truncated on disk-full; someone edited out currentFiles to 'slim' the file; a schema change renamed the field in one writer but not the validator.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Architecture update requires layers.json; baseline not advan
- Architecture update requires tour.json; baseline not advance
- Unresolved incremental symbol loss; baseline not advanced
- Import extraction reported failures: ${preview}${suffix}
- A valid previous graph is required for incremental symbol pr
AI-assisted analysis of Egonex-AI/Understand-Anything@07edf82a04 (2026-09-07).
Data as JSON: /api/errors/c350e128973c06b5.
Report an issue: GitHub.