{"record":{"id":"02b94efb893e6b7b","repo":"wavetermdev/waveterm","slug":"build-output-is-not-executable","errorCode":null,"errorMessage":"build output is not executable","messagePattern":"build output is not executable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/buildercontroller/buildercontroller.go","lineNumber":260,"sourceCode":"\t})\n\n\tfor _, line := range outputCapture.GetLines() {\n\t\tbc.outputBuffer.AddLine(line)\n\t}\n\n\tif err != nil {\n\t\tbc.handleBuildError(fmt.Errorf(\"build failed: %w\", err), resultCh)\n\t\treturn\n\t}\n\n\tinfo, err := os.Stat(cachePath)\n\tif err != nil {\n\t\tbc.handleBuildError(fmt.Errorf(\"build output not found: %w\", err), resultCh)\n\t\treturn\n\t}\n\n\tif runtime.GOOS != \"windows\" && info.Mode()&0111 == 0 {\n\t\tbc.handleBuildError(fmt.Errorf(\"build output is not executable\"), resultCh)\n\t\treturn\n\t}\n\n\tprocess, err := bc.runBuilderApp(ctx, appId, cachePath, builderEnv)\n\tif err != nil {\n\t\tbc.handleBuildError(fmt.Errorf(\"failed to run app: %w\", err), resultCh)\n\t\treturn\n\t}\n\n\tbc.lock.Lock()\n\tbc.process = process\n\tbc.setStatus_nolock(BuilderStatus_Running, process.Port, 0, \"\")\n\tbc.lock.Unlock()\n\n\ttime.Sleep(1 * time.Second)\n\n\tif resultCh != nil {\n\t\tbuildOutput := \"\"","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/buildercontroller/buildercontroller.go#L242-L278","documentation":"After locating the build output, the controller verifies the file has an execute permission bit (info.Mode()&0111) on non-Windows platforms. This literal error means the built binary exists but is not executable — the build produced a non-executable artifact or lost its permission bits.","triggerScenarios":"os.Stat succeeds but Mode()&0111 == 0 on linux/darwin — e.g. the output is a data file, the chmod step of the build was skipped, or the file was copied in a way that dropped the exec bit.","commonSituations":"Build pipeline change emits a bundle/archive instead of a binary; file moved over a filesystem that drops permissions (some network mounts, FAT/exFAT); manual copy of build output.","solutions":["chmod +x the binary and rebuild to confirm the pipeline sets exec bits","Verify TsunamiBuildInternal actually produced an executable (not an archive) at cachePath","Check the cache directory filesystem preserves permission bits","Fix the build step to chmod 0755 the output after MoveFileBack"],"exampleFix":"// before\n// build leaves output with 0644\n// after\nos.Chmod(cachePath, 0o755) // in build step before returning from TsunamiBuildInternal","handlingStrategy":"validation","validationCode":"info, err := os.Stat(binPath)\nif err == nil && runtime.GOOS != \"windows\" && info.Mode()&0111 == 0 {\n    os.Chmod(binPath, 0o755)\n}","typeGuard":null,"tryCatchPattern":"if err := runBuild(appId); err != nil {\n    if strings.Contains(err.Error(), \"not executable\") { os.Chmod(cachePath, 0o755) }\n}","preventionTips":["chmod 0755 build outputs in the build pipeline","Store build artifacts on permission-preserving filesystems","Don't hand-copy build outputs with cp -r stripping modes"],"tags":["go","permissions","build"],"backgroundTag":"file-not-executable","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}