golang/go · error
go %s%s%s: %v
Error message
go %s%s%s: %v
What it means
BuildInstallFunc wraps any error from the install action with the command name (cfg.CmdName, e.g. "build" or "install"), a separator, and the package import path. It is a user-facing prefix that contextualizes the underlying failure; the real cause is in the wrapped %v. For the -buildmode=shared action that installs a .so over multiple packages, a.Package is nil so the path is omitted.
Source
Thrown at src/cmd/go/internal/work/exec.go:2199
// TODO(rsc): There is a missing updateBuildID here,
// but we have to decide where to store the build ID in these files.
a.built = a.Target
return BuildToolchain.ldShared(b, a, a.Deps[0].Deps, a.Target, importcfg, a.Deps)
}
// BuildInstallFunc is the action for installing a single package or executable.
func BuildInstallFunc(b *Builder, ctx context.Context, a *Action) (err error) {
defer func() {
if err != nil {
// a.Package == nil is possible for the go install -buildmode=shared
// action that installs libmangledname.so, which corresponds to
// a list of packages, not just one.
sep, path := "", ""
if a.Package != nil {
sep, path = " ", a.Package.ImportPath
}
err = fmt.Errorf("go %s%s%s: %v", cfg.CmdName, sep, path, err)
}
}()
sh := b.Shell(a)
a1 := a.Deps[0]
a.buildID = a1.buildID
if a.json != nil {
a.json.BuildID = a.buildID
}
// If we are using the eventual install target as an up-to-date
// cached copy of the thing we built, then there's no need to
// copy it into itself (and that would probably fail anyway).
// In this case a1.built == a.Target because a1.built == p.Target,
// so the built target is not in the a1.Objdir tree that b.cleanup(a1) removes.
if a1.built == a.Target {
a.built = a.Target
if !a.buggyInstall {View on GitHub (pinned to b6b368adc5)
Solutions
- Read the wrapped error text after the colon - that is the real cause
- Address the underlying failure (missing module, compile error, permissions)
- Re-run with -x for full action tracing: `go install -x <pkg>`
Defensive patterns
Strategy: try-catch
Try / catch
// Unwrap the 'go <cmd> <pkg>: <cause>' wrapper to get the real error
out, err := cmd.CombinedOutput()
if err != nil {
// The real cause follows the last ': ' in the first error line
if i := bytes.LastIndex(out, []byte(": ")); i >= 0 {
log.Printf("underlying cause: %s", out[i+2:])
}
return err
} Prevention
- Always read the text after the colon - that is the actionable cause
- Use `go install -x` to trace which action failed
- Run `go build` before `go install` to separate compile from install failures
When it happens
Trigger: Fires in the deferred error handler of BuildInstallFunc whenever err != nil after the install action body - covering link errors, copy errors, permission errors, or any downstream build failure.
Common situations: Any `go install` or `go build` failure - the wrapped %v is the actionable part (missing dependency, compile error, permission denied, link failure).
Related errors
- %s: argument must be a clean package path
- %s: argument must not be a package in the standard library
- %s: %w
- %s (in %s): The go.mod file for the module providing named
- package %s not provided by module %s
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/8a1a4002ea88fdad.
Report an issue: GitHub.