golang/go · error

errors parsing go.work: %w

Error message

errors parsing go.work:
%w

What it means

go.work bytes were read but modfile.ParseWork rejected them (syntax/grammar error). The parser error is wrapped with %w under 'errors parsing go.work:'. This is distinct from read failures (1067) and from semantic validation failures (1065, 1066).

Source

Thrown at src/cmd/go/internal/modload/init.go:844

		if err := CheckGodebug("godebug", g.Key, g.Value); err != nil {
			return nil, nil, fmt.Errorf("error loading go.work:\n%s:%d: %w", base.ShortPath(path), g.Syntax.Start.Line, err)
		}
	}

	return wf, modRoots, nil
}

// ReadWorkFile reads and parses the go.work file at the given path.
func ReadWorkFile(path string) (*modfile.WorkFile, error) {
	path = base.ShortPath(path) // use short path in any errors
	workData, err := fsys.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("reading go.work: %w", err)
	}

	f, err := modfile.ParseWork(path, workData, nil)
	if err != nil {
		return nil, fmt.Errorf("errors parsing go.work:\n%w", err)
	}
	if f.Go != nil && gover.Compare(f.Go.Version, gover.Local()) > 0 && cfg.CmdName != "work edit" {
		base.Fatal(&gover.TooNewError{What: base.ShortPath(path), GoVersion: f.Go.Version})
	}
	return f, nil
}

// WriteWorkFile cleans and writes out the go.work file to the given path.
func WriteWorkFile(path string, wf *modfile.WorkFile) error {
	wf.SortBlocks()
	wf.Cleanup()
	out := modfile.Format(wf.Syntax)

	return os.WriteFile(path, out, 0o666)
}

// UpdateWorkGoVersion updates the go line in wf to be at least goVers,
// reporting whether it changed the file.

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Open go.work and fix the syntax at the parser-reported line/column.
  2. Remove git merge conflict markers (<<<<<<< ======= >>>>>>>) if present.
  3. Regenerate with 'go work init ./m1 ./m2 ...' (or 'go work edit') to get a syntactically valid file, then re-apply customizations.
  4. Validate by running 'gofmt -e go.work' or re-running the failing command to see the precise parse location.

Example fix

// before (go.work)
use (
    ./svc-a
    ./svc-b
// missing closing paren
// errors parsing go.work: 4:1: expected ')'

// after
use (
    ./svc-a
    ./svc-b
)
Defensive patterns

Strategy: validation

Validate before calling

// Parse go.work early to catch syntax errors with location.
data, err := os.ReadFile("go.work")
if err != nil && !os.IsNotExist(err) { return err }
if err == nil {
    if _, perr := modfile.ParseWork("go.work", data, nil); perr != nil {
        return fmt.Errorf("go.work parse error: %w", perr)
    }
}

Try / catch

out, err := exec.Command("go", "build", "./...").CombinedOutput()
if err != nil && bytes.Contains(out, []byte("errors parsing go.work")) {
    // regenerate from known module list rather than guessing the fix
    return fmt.Errorf("go.work malformed; recreate with 'go work init ...': %s", out)
}
return err

Prevention

When it happens

Trigger: go.work contains malformed syntax: unbalanced parens in a 'use ( ... )' block, stray tokens, bad directive verb, missing value, unterminated string. modfile.ParseWork returns a non-nil error and ReadWorkFile wraps it.

Common situations: Hand-edited go.work with a typo; merge conflict markers left in the file; a tool that writes partial go.work; copy-paste from docs that introduced smart quotes.

Related errors


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