golang/go · error

multiple toplevel scopes

Error message

multiple toplevel scopes

What it means

Thrown by putPrunedScopes in cmd/internal/dwarf when emitting DWARF variable scopes for a function. putscope starts at scope index 0 (the toplevel function scope) and is expected to consume scopes recursively, returning the index of the next unprocessed scope. If it returns less than len(scopes), there is more than one top-level scope for a single function — a structural invariant violation in the compiler's scope data, since each function must have exactly one outermost lexical scope.

Source

Thrown at src/cmd/internal/dwarf/dwarf.go:1192

	scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
	pvars := inlinedVarTable(&s.InlCalls)
	for k, s := range s.Scopes {
		var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
		for i := 0; i < len(s.Vars); i++ {
			_, found := pvars[s.Vars[i]]
			if !found {
				pruned.Vars = append(pruned.Vars, s.Vars[i])
			}
		}
		slices.SortFunc(pruned.Vars, byChildIndexCmp)
		scopes[k] = pruned
	}

	s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev)

	var encbuf [20]byte
	if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
		return errors.New("multiple toplevel scopes")
	}
	return nil
}

// Emit DWARF attributes and child DIEs for an 'abstract' subprogram.
// The abstract subprogram DIE for a function contains its
// location-independent attributes (name, type, etc). Other instances
// of the function (any inlined copy of it, or the single out-of-line
// 'concrete' instance) will contain a pointer back to this abstract
// DIE (as a space-saving measure, so that name/type etc doesn't have
// to be repeated for each inlined copy).
func PutAbstractFunc(ctxt Context, s *FnState) error {
	if logDwarf {
		ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
	}

	abbrev := DW_ABRV_FUNCTION_ABSTRACT
	Uleb128put(ctxt, s.Absfn, int64(abbrev))

View on GitHub (pinned to b6b368adc5)

Solutions

  1. File a bug at https://go.dev/issue with a minimal reproducer; this is almost always a compiler/DWARF bug rather than user error.
  2. As a workaround, build with -gcflags=-l (disable inlining) or -ldflags=-w (strip DWARF) to bypass the failing path.
  3. Try a different Go version — newer tip often has the fix; older stable may avoid the regression.
  4. Reduce the offending function (often a heavily-generic one) to isolate the trigger for the bug report.

Example fix

# before
$ go build ./...
# -> multiple toplevel scopes

# after (workaround while bug is open)
$ go build -ldflags=-w ./...
# or
$ go build -gcflags=-l ./...
Defensive patterns

Strategy: fallback

Validate before calling

// No caller-side prevention: this is a compiler-internal assertion.
// Detect the toolchain version to avoid known-bad releases.
func toolchainHasDwarfScopeBug() bool {
    // example predicate; substitute the range from the upstream issue
    v := runtime.Version()
    return strings.Contains(v, "devel") && strings.Contains(v, "2024-01")
}

Try / catch

// If the error surfaces during release builds, fall back to stripping DWARF.
out, err := build()
if err != nil && strings.Contains(err.Error(), "multiple toplevel scopes") {
    return buildWithFlags("-ldflags", "-w")
}

Prevention

When it happens

Trigger: This is essentially an internal compiler assertion surfaced during DWARF generation. It fires when the compiler's scope tree for a function has multiple roots (more than one scope with Parent == -1 or no enclosing scope). It can be triggered by unusual control-flow + generics/inlining combinations that confuse scope assignment. Almost never user-facing unless the user's code happens to hit a compiler bug.

Common situations: Hitting a Go compiler bug in DWARF scope generation — most often seen with heavy use of generics instantiation, inlined closures, or very recent/unstable Go versions. Building with -ldflags=-w or similar may avoid it but masks the underlying bug. Reproducible across builds of the same source with the same toolchain.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/d2f128efe9e44425. Report an issue: GitHub.