JuliusBrussee/caveman · error
executable identity unsupported on %s
Error message
executable identity unsupported on %s
What it means
Returned by runstate.processExecutable when it needs to identify the executable behind a PID but the current GOOS is not linux, darwin, or windows. This is a build-target problem: the code was compiled for a platform with no executable-identity strategy (e.g. freebsd, openbsd).
Source
Thrown at proxy/internal/runstate/runstate.go:230
// Windows validate()'s portBound probe carries the real liveness
// weight — a dead proxy is not listening.
return true
}
return process.Signal(syscall.Signal(0)) == nil
}
func processExecutable(pid int) (string, error) {
if runtime.GOOS == "linux" {
return os.Readlink(filepath.Join("/proc", strconv.Itoa(pid), "exe"))
}
if runtime.GOOS == "darwin" {
out, err := exec.Command("ps", "-o", "comm=", "-p", strconv.Itoa(pid)).Output()
return strings.TrimSpace(string(out)), err
}
if runtime.GOOS == "windows" {
return processExecutableWindows(pid)
}
return "", fmt.Errorf("executable identity unsupported on %s", runtime.GOOS)
}
func portBound(listen string) bool {
conn, err := net.DialTimeout("tcp", listen, 200*time.Millisecond)
if err != nil {
return false
}
_ = conn.Close()
return true
}
View on GitHub (pinned to 27d5a3981a)
Solutions
- Build/run on a supported platform: linux, darwin, or windows
- If you must run on another unix, port processExecutable for that GOOS (e.g. sysctl KERN_PROC_PATHNAME on the BSDs) and submit it upstream
- As an operator fallback, delete the stale run-state JSON under home/run/ so ownership checks skip the unsupported path
- Check your build script's GOOS/GOARCH matrix — often the wrong value leaks from a cross-compile variable
Example fix
// before: unsupported platform returns error
return "", fmt.Errorf("executable identity unsupported on %s", runtime.GOOS)
// after (porting example, BSD):
// sysctl kern.proc.pathname.<pid> returns the executable path
mib := []int{CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid}
// ... sysctl call, return string(path) Defensive patterns
Strategy: validation
Validate before calling
if runtime.GOOS != "linux" && runtime.GOOS != "darwin" && runtime.GOOS != "windows" {
log.Fatal("executable-identity checks unsupported on " + runtime.GOOS + "; use linux/darwin/windows")
} Type guard
func executableIdentitySupported() bool {
switch runtime.GOOS {
case "linux", "darwin", "windows":
return true
}
return false
} Try / catch
_, err := runstate.New(listen, mode, owner, version)
if err != nil && strings.Contains(err.Error(), "executable identity unsupported") {
// platform gap: either skip stale-state ownership probing or clear home/run/*.json
os.RemoveAll(filepath.Join(home, "run"))
} Prevention
- Gate builds on the supported GOOS trio in CI (go build for linux/darwin/windows only)
- Clear stale run-state files when moving a home to an unsupported platform
- Port processExecutable before adding a new target OS
When it happens
Trigger: Compiling the proxy for an unsupported GOOS (GOOS=freebsd go build ...) and then exercising the run-state ownership path that calls processExecutable — typically stale-state detection that wants to know if the recorded PID still belongs to a caveman binary.
Common situations: Cross-compiling to run on a NAS/BSD system; building in a container with an unusual toolchain default; future Go ports (plan9, js/wasm) where the proc APIs do not exist at all.
Related errors
- open sqlite %q: %w
- caveman build: dataResidency is not enforced yet; refusing t
- caveman build: requiredFixturePassRate must be in (0,1]
- caveman build: qualityRetention must be in (0,1]
- caveman build: config must export defineBuild()
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/14d48794b924899e.
Report an issue: GitHub.