goreleaser/goreleaser · error
invalid goos: %s
Error message
invalid goos: %s
What it means
listTargets validates every computed build target's GOOS against the list of valid Go operating systems (validGoos). This error means a target's goos value is not a real Go-supported OS, so the build would fail later. It is a configuration validation error thrown early by the golang builder.
Source
Thrown at internal/builders/golang/targets.go:115
"GOMIPS=" + t.Gomips,
"GOMIPS64=" + t.Gomips,
"GOPPC64=" + t.Goppc64,
"GORISCV64=" + t.Goriscv64,
}
}
func listTargets(build config.Build) ([]string, error) {
//nolint:prealloc
var targets []Target
//nolint:prealloc
var result []string
built, err := allBuildTargets(build)
if err != nil {
return result, err
}
for _, target := range built {
if !slices.Contains(validGoos, target.Goos) {
return result, fmt.Errorf("invalid goos: %s", target.Goos)
}
if !slices.Contains(validGoarch, target.Goarch) {
return result, fmt.Errorf("invalid goarch: %s", target.Goarch)
}
if target.Goamd64 != "" && !slices.Contains(validGoamd64, target.Goamd64) {
return result, fmt.Errorf("invalid goamd64: %s", target.Goamd64)
}
if target.Go386 != "" && !slices.Contains(validGo386, target.Go386) {
return result, fmt.Errorf("invalid go386: %s", target.Go386)
}
if target.Goarm64 != "" && !validGoarm64.MatchString(target.Goarm64) {
return result, fmt.Errorf("invalid goarm64: %s", target.Goarm64)
}
if target.Gomips != "" && !slices.Contains(validGomips, target.Gomips) {
return result, fmt.Errorf("invalid gomips: %s", target.Gomips)
}
if target.Goppc64 != "" && !slices.Contains(validGoppc64, target.Goppc64) {
return result, fmt.Errorf("invalid goppc64: %s", target.Goppc64)View on GitHub (pinned to f5edd73956)
Solutions
- Fix the `goos` entries in the build config, using valid values: aix, android, darwin, dragonfly, freebsd, illumos, ios, js, linux, netbsd, openbsd, plan9, solaris, wasip1, windows
- Run `go tool dist list` to see all valid GOOS/GOARCH pairs
- Check for typos (e.g. `linuxs` → `linux`, `macos` → `darwin`)
- Run `goreleaser check` to validate the config before releasing
Example fix
// .goreleaser.yaml // before builds: - goos: [macos, linux] // after builds: - goos: [darwin, linux]
Defensive patterns
Strategy: validation
Validate before calling
var validGoos = map[string]bool{
"aix": true, "android": true, "darwin": true, "dragonfly": true,
"freebsd": true, "illumos": true, "ios": true, "js": true,
"linux": true, "netbsd": true, "openbsd": true, "plan9": true,
"solaris": true, "wasip1": true, "windows": true,
}
for _, goos := range cfg.Builds[0].Goos {
if !validGoos[goos] {
return fmt.Errorf("invalid goos %q", goos)
}
} Prevention
- Validate the config with `goreleaser check` before releasing
- Use `go tool dist list` as the source of truth for GOOS names
- Remember macOS is `darwin` in Go, not `macos`
- Keep goos lists in one shared config to avoid copy-paste drift
When it happens
Trigger: Setting an unknown `goos` in a build's targets/overrides (e.g. a typo like `goos: linuxs` or `macos` instead of `darwin`) so the resolved target contains an invalid GOOS.
Common situations: Typos in .goreleaser.yaml goos lists; using an OS name that Go does not support (e.g. `windowsphone`, `ios` misuse); copy-pasting OS names from other tooling with different naming conventions.
Related errors
AI-assisted analysis of goreleaser/goreleaser@f5edd73956 (2026-09-05).
Data as JSON: /api/errors/1206dffbcf0e12da.
Report an issue: GitHub.