Egonex-AI/Understand-Anything · error · Error

Invalid assembled graph

Error message

Invalid assembled graph

What it means

`validateIncrementalSymbols` loads `assembled-graph.json` (unless a graph was passed in) and requires both `graph.nodes` and `graph.edges` to be arrays before hashing and validating it. If either is missing or not an array, the graph is structurally unusable and it throws 'Invalid assembled graph'.

Source

Thrown at understand-anything-plugin/skills/understand/validate-incremental-symbols.mjs:325

  // Git compares normalized contents, including repository clean/EOL rules.
  if (paths.length) git(projectRoot, [
    'diff', '--quiet', '--no-ext-diff', plan.headCommit, '--', ...paths.map(path => `:(literal)${path}`),
  ]);
  return { plan, baseline };
}

export async function validateIncrementalSymbols(projectRoot, { graph, intermediateDir } = {}) {
  const core = await getCore();
  intermediateDir ??= join(core.resolveUaDir(projectRoot), 'intermediate');
  const reportPath = join(intermediateDir, 'incremental-symbol-report.json');
  const report = { version: 1, ok: false, files: [], unresolvedFiles: [], errors: [] };
  const graphFromDisk = graph === undefined;
  try {
    const { plan, baseline } = loadSymbolContext(projectRoot, intermediateDir);
    report.baseCommit = plan.baseCommit;
    report.headCommit = plan.headCommit;
    graph ??= readJson(join(intermediateDir, 'assembled-graph.json'));
    if (!Array.isArray(graph.nodes) || !Array.isArray(graph.edges)) throw new Error('Invalid assembled graph');
    report.graphHash = createHash('sha256').update(JSON.stringify(graph)).digest('hex');
    let parser;
    const evidenceByPath = new Map();
    const parseHead = async path => {
      if (evidenceByPath.get(path)?.head) return evidenceByPath.get(path).head;
      if (!parser) {
        parser = new core.TreeSitterPlugin(core.builtinLanguageConfigs.filter(config => config.treeSitter));
        await parser.init();
      }
      // :./ keeps git-show relative to projectRoot, including monorepo subdirectories.
      const headContent = git(projectRoot, ['show', `${plan.headCommit}:./${path}`]);
      const evidence = { head: parser.analyzeFileStrict(path, headContent) };
      evidenceByPath.set(path, evidence);
      return evidence.head;
    };
    const parseRevisions = async path => {
      await parseHead(path);
      const evidence = evidenceByPath.get(path);

View on GitHub (pinned to 07edf82a04)

Solutions

  1. Regenerate `assembled-graph.json` by re-running the graph assembly step.
  2. Validate the JSON shape: it must contain `nodes: []` and `edges: []` (`jq '.nodes|type, .edges|type' assembled-graph.json`).
  3. If passing a graph programmatically, ensure it includes array-valued `nodes` and `edges`.
  4. Check disk space / write errors if the file appears truncated, and re-run assembly after cleanup.

Example fix

// before: passing a bare object
await validateIncrementalSymbols({ projectRoot, intermediateDir, graph: {} });

// after: pass a complete graph or let it load from disk
const graph = JSON.parse(readFileSync(join(intermediateDir, 'assembled-graph.json'), 'utf8'));
if (!Array.isArray(graph.nodes) || !Array.isArray(graph.edges)) throw new Error('bad graph');
await validateIncrementalSymbols({ projectRoot, intermediateDir, graph });
Defensive patterns

Strategy: type-guard

Validate before calling

const graph = JSON.parse(readFileSync(join(intermediateDir,'assembled-graph.json'),'utf8'));
if (!Array.isArray(graph.nodes) || !Array.isArray(graph.edges)) {
  await rerunGraphAssembly();
}

Type guard

function isValidGraph(g) {
  return g != null && typeof g === 'object'
    && Array.isArray(g.nodes) && Array.isArray(g.edges);
}

Try / catch

try {
  await validateIncrementalSymbols({ projectRoot, intermediateDir });
} catch (err) {
  if (err.message === 'Invalid assembled graph') {
    await rerunGraphAssembly(); // rebuild assembled-graph.json
  } else throw err;
}

Prevention

When it happens

Trigger: Calling `validateIncrementalSymbols` when `assembled-graph.json` in the intermediate directory is absent-but-replaced by malformed JSON output, truncated, or written without `nodes`/`edges` array fields — or when a caller passes a `graph` argument lacking those arrays.

Common situations: The graph-assembly agent crashed mid-write leaving a partial file; disk-full truncated the JSON; an older schema stored nodes under a different key; a caller passed a hand-built object like `{}` instead of a full graph.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Egonex-AI/Understand-Anything@07edf82a04 (2026-09-07). Data as JSON: /api/errors/6e8f7dbb2f14048c. Report an issue: GitHub.