{"record":{"id":"a02574960e7de3aa","repo":"wavetermdev/waveterm","slug":"gofmt-not-found-at-s-w","errorCode":null,"errorMessage":"gofmt not found at %s: %w","messagePattern":"gofmt not found at (.+?): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/waveapputil/waveapputil.go","lineNumber":51,"sourceCode":"\n\tif goPath == \"\" {\n\t\tvar err error\n\t\tgoPath, err = build.FindGoExecutable()\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\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}","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/waveapputil/waveapputil.go#L33-L69","documentation":"ResolveGoFmtPath locates the gofmt binary next to the configured/discovered Go toolchain (settings.TsunamiGoPath, falling back to build.FindGoExecutable) and stats <goDir>/gofmt[.exe]. If os.Stat fails, the error is wrapped as 'gofmt not found at %s'. It means the Go installation directory does not contain a gofmt binary.","triggerScenarios":"Calling FormatGoFile/FormatGoCode when gofmt is absent from the resolved Go bin directory: os.Stat returns ENOENT (file missing) or the path is otherwise unstattable (broken symlink, permission on parent dir).","commonSituations":"TsunamiGoPath setting points at a non-Go directory or a stale path after a Go upgrade/uninstall; only the go binary was copied without the rest of the toolchain; partial Go installation (gofmt removed by antivirus or cleanup tool); PATH finds 'go' but bin dir is incomplete.","solutions":["Check the resolved path in the error and install/move gofmt there (it ships with the Go toolchain)","Fix the TsunamiGoPath setting to point to a real Go installation (directory containing go and gofmt)","Run 'which go' / 'go env GOROOT' and verify gofmt exists at GOROOT/bin/gofmt","Reinstall Go if the toolchain is incomplete"],"exampleFix":"// before\n// settings.TsunamiGoPath = \"/opt/old-go/bin/go\" (stale, gofmt missing)\n// after\n// settings.TsunamiGoPath = \"/usr/local/go/bin/go\"\n// ls /usr/local/go/bin  ->  go  gofmt","handlingStrategy":"validation","validationCode":"goPath := settings.TsunamiGoPath\nif goPath == \"\" { goPath, _ = build.FindGoExecutable() }\ngofmt := filepath.Join(filepath.Dir(goPath), gofmtName())\nif _, err := os.Stat(gofmt); err != nil {\n    return fmt.Errorf(\"precheck: %w\", err)\n}","typeGuard":"func gofmtAvailable() bool {\n    p, err := waveapputil.ResolveGoFmtPath()\n    return err == nil && p != \"\"\n}","tryCatchPattern":"// FormatGoCode silently falls back to unformatted content on error;\n// call ResolveGoFmtPath directly to surface the problem:\nif _, err := waveapputil.ResolveGoFmtPath(); err != nil {\n    log.Printf(\"gofmt unavailable, formatting disabled: %v\", err)\n}","preventionTips":["Keep TsunamiGoPath pointing at a complete Go installation","After Go upgrades, verify GOROOT/bin still contains gofmt","Never copy only the 'go' binary without its sibling tools"],"tags":["go","toolchain","filesystem"],"backgroundTag":"binary-not-found","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}