{"record":{"id":"a43c78ed9736f9c5","repo":"wavetermdev/waveterm","slug":"gofmt-is-not-executable-s","errorCode":null,"errorMessage":"gofmt is not executable: %s","messagePattern":"gofmt is not executable: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/waveapputil/waveapputil.go","lineNumber":59,"sourceCode":"\n\tgoDir := filepath.Dir(goPath)\n\tgofmtName := \"gofmt\"\n\tif runtime.GOOS == \"windows\" {\n\t\tgofmtName = \"gofmt.exe\"\n\t}\n\tgofmtPath := filepath.Join(goDir, gofmtName)\n\n\tinfo, err := os.Stat(gofmtPath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"gofmt not found at %s: %w\", gofmtPath, err)\n\t}\n\n\tif info.IsDir() {\n\t\treturn \"\", fmt.Errorf(\"gofmt path is a directory: %s\", gofmtPath)\n\t}\n\n\tif info.Mode()&0111 == 0 {\n\t\treturn \"\", fmt.Errorf(\"gofmt is not executable: %s\", gofmtPath)\n\t}\n\n\treturn gofmtPath, nil\n}\n\nfunc FormatGoCode(contents []byte) []byte {\n\tgofmtPath, err := ResolveGoFmtPath()\n\tif err != nil {\n\t\treturn contents\n\t}\n\n\tcmd := exec.Command(gofmtPath)\n\tcmd.Stdin = bytes.NewReader(contents)\n\tformattedOutput, err := cmd.Output()\n\tif err != nil {\n\t\treturn contents\n\t}\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/waveapputil/waveapputil.go#L41-L77","documentation":"After confirming the gofmt path exists and is a file, ResolveGoFmtPath checks the executable bit (info.Mode()&0111). If no execute permission is set, it returns 'gofmt is not executable: %s' rather than letting exec fail later. (On Windows this check is effectively always satisfied.)","triggerScenarios":"gofmt exists as a regular file at <goDir>/gofmt but has no +x bits — e.g. copied with cp without -p from a non-executable source, extracted from a zip that lost permission bits, or on a mount with noexec/umask stripping exec bits.","commonSituations":"Home directory mounted with noexec; archive extraction tool dropped the executable bit; file synced via cloud drive or copied from Windows losing Unix modes; overly restrictive umask during install.","solutions":["chmod +x <gofmt path> on the reported path","Re-copy the binary preserving modes: 'install -m 755 src dst' or extract with a tool that preserves permissions","Check the mount options (noexec) and remount with exec if applicable","Verify with 'ls -l' that the owner has execute permission"],"exampleFix":"// before\n-rw-r--r-- gofmt\n// after\n# chmod +x /usr/local/go/bin/gofmt\n-rwxr-xr-x gofmt","handlingStrategy":"validation","validationCode":"p, err := waveapputil.ResolveGoFmtPath()\nif err != nil { return err }\nif info, err := os.Stat(p); err == nil && info.Mode()&0111 == 0 {\n    return fmt.Errorf(\"precheck: %s lacks exec bit\", p)\n}","typeGuard":"func hasExecBit(path string) bool {\n    info, err := os.Stat(path)\n    return err == nil && info.Mode()&0111 != 0\n}","tryCatchPattern":"if _, err := waveapputil.ResolveGoFmtPath(); err != nil {\n    if strings.Contains(err.Error(), \"not executable\") {\n        // attempt repair: os.Chmod(path, 0755) if the file is owned by the user\n    }\n    return err\n}","preventionTips":["Install binaries with 'install -m 755' or extract with permission-preserving tools","Check for noexec mounts in the Go install location","After copying binaries between OSes, re-check permission bits"],"tags":["go","permissions","toolchain"],"backgroundTag":"permission-denied","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}