abhigyanpatwari/GitNexus · warning

[cfg] Go: unresolved goto label "${label}" routed to EXIT ($

Error message

[cfg] Go: unresolved goto label "${label}" routed to EXIT (${froms.length} site(s))

What it means

flushGotos() in the Go CFG visitor runs once after the body walk: any forward goto whose label never appeared in the function is routed to the EXIT node to preserve a single-exit graph, and each unresolved label is logged via console.warn. In valid Go the compiler rejects undefined labels, so this warning almost always indicates generated/partial files or a parse-level divergence rather than a user bug.

Source

Thrown at gitnexus/src/core/ingestion/cfg/visitors/go.ts:495

    if (normalExits.length > 0) {
      this.builder.connect(normalExits, lifo[0].entry, 'return');
      for (let i = 0; i + 1 < lifo.length; i++) {
        this.builder.edge(lifo[i].entry, lifo[i + 1].entry, 'finally-return');
      }
    }
    // After the outermost defer runs, control reaches EXIT.
    return [lifo[lifo.length - 1].entry];
  }

  /**
   * Route any forward `goto`s whose label never appeared in the function to EXIT
   * (single-exit preserved) and log them so a dropped jump is never silent (R4).
   * Called once after the body walk.
   */
  flushGotos(builder: CfgBuilder): void {
    for (const [label, froms] of this.pendingGotos) {
      // eslint-disable-next-line no-console
      console.warn(
        `[cfg] Go: unresolved goto label "${label}" routed to EXIT (${froms.length} site(s))`,
      );
      for (const from of froms) builder.edge(from, builder.exitIndex, 'seq');
    }
    this.pendingGotos.clear();
  }

  private visitIf(stmt: SyntaxNode): TraversalResult {
    const cond = stmt.childForFieldName('condition') ?? stmt;
    const init = stmt.childForFieldName('initializer');
    // The header block carries the (optional) initializer's facts AND the
    // condition's facts — both evaluate before the branch.
    const header = this.builder.newBlock(
      init ? startLineOf(init) : startLineOf(stmt),
      endLineOf(cond),
      init ? `${init.text}; ${cond.text}` : cond.text,
      'normal',
      this.harvest.facts(cond),

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Verify the file compiles (go build / go vet the module) — in valid Go every goto label exists
  2. Exclude codegen templates and testdata containing such gotos from analysis via ignore rules
  3. Accept the EXIT routing — it keeps the CFG single-exit and the dropped jump is reported rather than silent

Example fix

// before — template file with a goto whose label lives in commented-out code
goto retry  // label `retry:` only exists under a build tag

// after — restore the label or remove the goto
retry:
// ...
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-check: in valid Go every goto label is defined in the same function
const gotoLabels = [...source.matchAll(/\bgoto\s+(\w+)\b/g)].map((m) => m[1]);
const defined = new Set([...source.matchAll(/^\s*(\w+)\s*:/gm)].map((m) => m[1]));
const unresolved = gotoLabels.filter((l) => !defined.has(l));
if (unresolved.length > 0) {
  console.warn(`file would not compile — gotos without labels: ${[...new Set(unresolved)].join(', ')}`);
}

Type guard

function goFileHasResolvableLabels(source: string): boolean {
  const gotos = [...source.matchAll(/\bgoto\s+(\w+)\b/g)].map((m) => m[1]);
  const defined = new Set([...source.matchAll(/^\s*(\w+)\s*:/gm)].map((m) => m[1]));
  return gotos.every((l) => defined.has(l));
}

Prevention

When it happens

Trigger: Analyzing partial or syntactically odd Go files (codegen templates, testdata) where a goto's label sits in code the walker never registered; malformed Go that would not compile but still parses.

Common situations: Codegen templates or example snippets committed as .go files; truncated files; vendored generated code whose build-time transformations are not visible to the parser.

Related errors


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