PureGo Version
0.10 branch (v0.10.0)
Operating System
Go Version (go version)
Go 1.20.x through 1.23.x (reproduced with go1.20.14, go1.22.12 and go1.23.11 on darwin/arm64)
What steps will reproduce the problem?
CI on the 0.10 branch fails now that GitHub's macos-latest label has migrated to macOS 26:
https://github.com/ebitengine/purego/actions/runs/29646451569
The Test with Go 1.22.x on macos-latest job fails in the go test step. Every other error in that run is The operation was canceled. from fail-fast.
Locally, on macOS 26.5 (arm64):
git checkout 0.10
env CGO_ENABLED=1 go1.22.12 test -c -o purego.test .
./purego.test -test.run TestOS
What is the expected result?
The test binary runs, as it did while macos-latest was macOS 15. The same job passed on
https://github.com/ebitengine/purego/actions/runs/26362358247 (2026-05-24), where the runner image was macos-15-arm64 / macOS 15.7.7.
What happens instead?
The binary is rejected by dyld before main runs:
dyld[9810]: missing LC_UUID load command in /var/folders/.../b001/purego.test
dyld[9810]: missing LC_UUID load command
signal: abort trap
FAIL github.com/ebitengine/purego 0.003s
Anything else you feel useful to add?
Cause
This is not a purego bug. On macOS 26, dyld refuses to exec a Mach-O binary that has no LC_UUID load command when the binary targets the macOS 26 SDK and links CoreFoundation. Go's internal linker only emits LC_UUID when -B is passed, and -B gobuildid became the default only in Go 1.24 (cmd/link/internal/ld/main.go: if *flagHostBuildid == "" && *flagBuildid != "" { *flagHostBuildid = "gobuildid" }, present in go1.24.0, absent in go1.23.12).
CoreFoundation is pulled in by the cgo-enabled net package, which is why CGO_ENABLED=0 passes and CGO_ENABLED=1 fails within the same step. The -race steps fail for the same reason.
Measured on macOS 26.5 with the 0.10 tree:
| Go |
LC_UUID |
LC_BUILD_VERSION |
CGO_ENABLED=1 test binary |
| 1.18.10 |
absent |
minos 12.0 / sdk 12.3 |
runs |
| 1.19.13 |
absent |
minos 12.x |
runs |
| 1.20.14 |
absent |
minos 26.0 / sdk 26.5 |
dyld: missing LC_UUID |
| 1.21.x |
absent (linker has no emission code) |
— |
expected to fail |
| 1.22.12 |
absent |
minos 26.x |
dyld: missing LC_UUID |
| 1.23.11 |
absent |
minos 26.x |
dyld: missing LC_UUID |
| 1.25.7 / 1.26.5 |
present |
minos 26.x |
runs |
Go 1.18/1.19 survive only because their linker stamps an old SDK version in LC_BUILD_VERSION, so dyld applies the pre-26 rules.
Proposed fix
Pin the macOS runner to macos-15 in .github/workflows/test.yml on the 0.10 branch. The branch's supported Go range (1.18–1.26) cannot be narrowed, so the affected toolchains have to keep running on a pre-26 runner. macos-15 is still current and non-deprecated (macos-14 is deprecated), and main continues to exercise macOS 26 with Go 1.25+.
Alternatives that were considered and rejected:
-ldflags=-B=gobuildid on the macOS test commands: works for Go 1.22/1.23, but Go 1.20/1.21 reject the flag (-B argument must start with 0x: gobuildid) and cannot emit LC_UUID at all.
- Dropping Go 1.20–1.23 from the macOS matrix: loses coverage that
macos-15 can still provide.
main needs no change: #469 reduced its matrix to Go 1.25+, all of which emit LC_UUID by default. The same commit passed on main and failed on 0.10 on the same day.
Note for users: any Go program built with Go 1.20–1.23 that links CoreFoundation fails to launch on macOS 26, regardless of purego. The workaround is to build with Go 1.24 or later.
Filed by Claude (Claude Code), on behalf of @hajimehoshi.
PureGo Version
0.10branch (v0.10.0)Operating System
Go Version (
go version)Go 1.20.x through 1.23.x (reproduced with go1.20.14, go1.22.12 and go1.23.11 on darwin/arm64)
What steps will reproduce the problem?
CI on the
0.10branch fails now that GitHub'smacos-latestlabel has migrated to macOS 26:https://github.com/ebitengine/purego/actions/runs/29646451569
The
Test with Go 1.22.x on macos-latestjob fails in thego teststep. Every other error in that run isThe operation was canceled.from fail-fast.Locally, on macOS 26.5 (arm64):
What is the expected result?
The test binary runs, as it did while
macos-latestwas macOS 15. The same job passed onhttps://github.com/ebitengine/purego/actions/runs/26362358247 (2026-05-24), where the runner image was
macos-15-arm64/ macOS 15.7.7.What happens instead?
The binary is rejected by dyld before
mainruns:Anything else you feel useful to add?
Cause
This is not a purego bug. On macOS 26, dyld refuses to exec a Mach-O binary that has no
LC_UUIDload command when the binary targets the macOS 26 SDK and links CoreFoundation. Go's internal linker only emitsLC_UUIDwhen-Bis passed, and-B gobuildidbecame the default only in Go 1.24 (cmd/link/internal/ld/main.go:if *flagHostBuildid == "" && *flagBuildid != "" { *flagHostBuildid = "gobuildid" }, present in go1.24.0, absent in go1.23.12).CoreFoundation is pulled in by the cgo-enabled
netpackage, which is whyCGO_ENABLED=0passes andCGO_ENABLED=1fails within the same step. The-racesteps fail for the same reason.Measured on macOS 26.5 with the
0.10tree:LC_UUIDLC_BUILD_VERSIONCGO_ENABLED=1test binaryGo 1.18/1.19 survive only because their linker stamps an old SDK version in
LC_BUILD_VERSION, so dyld applies the pre-26 rules.Proposed fix
Pin the macOS runner to
macos-15in.github/workflows/test.ymlon the0.10branch. The branch's supported Go range (1.18–1.26) cannot be narrowed, so the affected toolchains have to keep running on a pre-26 runner.macos-15is still current and non-deprecated (macos-14is deprecated), andmaincontinues to exercise macOS 26 with Go 1.25+.Alternatives that were considered and rejected:
-ldflags=-B=gobuildidon the macOS test commands: works for Go 1.22/1.23, but Go 1.20/1.21 reject the flag (-B argument must start with 0x: gobuildid) and cannot emitLC_UUIDat all.macos-15can still provide.mainneeds no change: #469 reduced its matrix to Go 1.25+, all of which emitLC_UUIDby default. The same commit passed onmainand failed on0.10on the same day.Note for users: any Go program built with Go 1.20–1.23 that links CoreFoundation fails to launch on macOS 26, regardless of purego. The workaround is to build with Go 1.24 or later.
Filed by Claude (Claude Code), on behalf of @hajimehoshi.