golang/go · error

invalid version %q

Error message

invalid version %q

What it means

The `-macos` and `-macsdk` linker flags (exposed via `-ldflags='-X cmd/link/internal/ld.macos=...'`-style mechanisms, or the internal `macVersionFlag.Set`) parse a dot-separated version string into exactly three byte-sized components (major.minor.patch). Parsing fails if the string is not three dot-separated integers, or if any component is outside 0–255, because macOS encodes the version in a single uint32 as `major<<16 | minor<<8 | patch`.

Source

Thrown at src/cmd/link/internal/ld/macho.go:433

func (f *macVersionFlag) Set(s string) error {
	var parsed macVersionFlag
	nums := strings.Split(s, ".")
	if len(nums) > 3 {
		goto Error
	}
	for i, num := range nums {
		n, err := strconv.Atoi(num)
		if err != nil || n < 0 || n > 0xFF {
			goto Error
		}
		parsed[i] = byte(n)
	}
	// success, now modify f
	*f = parsed
	return nil

Error:
	return fmt.Errorf("invalid version %q", s)
}

func (f *macVersionFlag) version() uint32 {
	return uint32(f[0])<<16 | uint32(f[1])<<8 | uint32(f[2])
}

var (
	// On advice from Apple engineers, we keep macOS set to the
	// oldest supported macOS version but keep macSDK to the newest
	// tested OS/SDK version. If these defaults are not good enough,
	// the -macos and -macsdk linker flags can override them.
	// For past problems involving these values, see
	//	go.dev/issue/30488
	//	go.dev/issue/56784
	//	go.dev/issue/77917
	macOS  = macVersionFlag{13, 0, 0}
	macSDK = macVersionFlag{26, 2, 0}
)

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Use exactly three dot-separated integers in the range 0–255, e.g. `-macos 11.0.0`.
  2. Trim any suffix from the SDK version before passing it: strip build numbers, arch tags, and trailing dots.
  3. If you do not need to override the default, remove the `-macos`/`-macsdk` flag entirely — the linker ships sane defaults.
  4. Validate the version string with a shell check (regex `^[0-9]{1,3}(\.[0-9]{1,3}){2}$`) before invoking `go build`.

Example fix

# before
go build -ldflags='-macos 13.6.1-build42' ./...

# after
MACOS=$(xcrun --show-sdk-version | cut -d. -f1-3)
go build -ldflags="-macos $MACOS" ./...
Defensive patterns

Strategy: validation

Validate before calling

# Validate a macOS version string before passing it to -ldflags
validate_macos_version() {
  local v="$1"
  if ! printf '%s' "$v" | grep -Eq '^[0-9]{1,3}(\.[0-9]{1,3}){2}$'; then
    echo "invalid macOS version: $v (need N.N.N, each 0-255)" >&2
    return 1
  fi
  IFS=. read -r a b c <<<"$v"
  for n in "$a" "$b" "$c"; do [ "$n" -le 255 ] || { echo "$n > 255" >&2; return 1; }; done
}
validate_macos_version "$MACOS_VERSION" || exit 1

Type guard

// Type guard for a Go-side version-string helper
func isValidMacVersion(s string) bool {
    parts := strings.Split(s, ".")
    if len(parts) != 3 { return false }
    for _, p := range parts {
        n, err := strconv.Atoi(p)
        if err != nil || n < 0 || n > 0xFF { return false }
    }
    return true
}

Try / catch

# In CI: validate before building; fall back to default if invalid
if validate_macos_version "$MACOS_VERSION"; then
  go build -ldflags="-macos $MACOS_VERSION" ./...
else
  echo 'invalid version; using linker default' >&2
  go build ./...
fi

Prevention

When it happens

Trigger: Passing `-ldflags='-macos 10.15.7.1'` (four components), `-macos 999.0` (>255), `-macos latest` (non-numeric), or `-macos 10` (one component). Also triggered by automation that interpolates an SDK version string with extra fields (e.g. a build number or arch suffix).

Common situations: CI scripts deriving `-macos` from `xcrun --show-sdk-version` and forgetting to trim a trailing build identifier; hardcoding a version that exceeds 255 in one field after a macOS release; copy-pasting an iOS version string into a macOS flag.

Related errors


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