[BUG] Go binaries hang 30-60 seconds in Bash tool on macOS (stdin issue)

Status Fixed / completed
Maintainer reply None cached
Activity 6 comments · opened Dec 5, 2025 · closed Jan 5, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Go binaries (go, bd, custom programs) hang for minutes before succeeding when executed via Claude Code's Bash tool on macOS. Works instantly on Linux. Standard Unix commands (date, ls, pwd) work fine. Redirecting stdin makes go binaries work normally.

Environment

  • macOS: Darwin 24.6.0 (arm64)
  • Go: go1.25.5 darwin/arm64
  • Claude Code: 2.0.30-2.0.59 (tested multiple versions)
  • Shell: Tested both zsh and bash
  • Terminal: Tested iTerm2, VSCode and Terminal.app

Reproduction

# These hang 30-60 seconds on macOS:
go version
bd version

# These work instantly:
npm
date
pwd
ls

Root Cause

Claude Code's Bash tool provides stdin as a named pipe (Srw-rw-rw-) that blocks on read. Test program shows:

stat, _ := os.Stdin.Stat()
fmt.Printf("Mode: %v\n", stat.Mode())  // Output: Srw-rw-rw-
fmt.Printf("Is CharDevice: %v\n", (stat.Mode() & os.ModeCharDevice) != 0)  // Output: false

// Attempting to read blocks for 2+ seconds

The Go runtime appears to check stdin during initialization, causing the hang.

Workaround

Redirect stdin to /dev/null:

go version < /dev/null

Platform Behavior

  • macOS: Hangs
  • Ubuntu 24.04.3: Works instantly

This seems macOS-specific, not shell or terminal-specific.

What Should Happen?

go binaries should run in claude code for the same durations they run outside claude code.

Error Messages/Logs

n/a

Steps to Reproduce

launch claude code on MacOS.

prompt claude code to run "go version"

Claude Model

Opus

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.0.59

Platform

AWS Bedrock

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

_No response_

View original on GitHub ↗

6 Comments

github-actions[bot] · 10 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/8049
  2. https://github.com/anthropics/claude-code/issues/12650
  3. https://github.com/anthropics/claude-code/issues/12507

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

jimweller · 10 months ago

This is similar to 12507, but for MacOS. Downgrading to 2.0.25 like that issue did not work for me on MacOS. The spawn() suggestion from that issue seems sane.

I tried three different languages to reproduce stdin behaviors with the claude Bash tool. node and go both fail. python succeeds. They do eventually succeed when the pipe finally produces EOF.

node

const fs = require('fs');

console.log("Checking stdin...");
const stats = fs.fstatSync(process.stdin.fd);
console.log(`Is CharDevice: ${stats.isCharacterDevice()}`);
console.log(`Is FIFO: ${stats.isFIFO()}`);
console.log(`Is Socket: ${stats.isSocket()}`);

console.log("Testing if stdin blocks...");
const start = Date.now();

// Set timeout for stdin read
const timeout = setTimeout(() => {
    console.log(`Stdin blocked for ${Date.now() - start}ms`);
    process.exit(0);
}, 2000);

// Try to read from stdin
process.stdin.once('readable', () => {
    clearTimeout(timeout);
    console.log("Stdin had data available");
    process.exit(0);
});

go

package main
import (
    "fmt"
    "os"
    "time"
)
func main() {
    fmt.Println("Checking stdin...")
    stat, _ := os.Stdin.Stat()
    fmt.Printf("Mode: %v\n", stat.Mode())
    fmt.Printf("Is CharDevice: %v\n", (stat.Mode() & os.ModeCharDevice) != 0)
    
    // Test if select would block
    fmt.Println("Testing if stdin would block...")
    done := make(chan bool, 1)
    go func() {
        var buf [1]byte
        os.Stdin.Read(buf[:])
        done <- true
    }()
    
    select {
    case <-done:
        fmt.Println("Stdin had data or EOF")
    case <-time.After(2 * time.Second):
        fmt.Println("Stdin blocked for 2+ seconds")
    }
}

python

import sys
import select
import os
import stat

print("Checking stdin...")
st = os.fstat(sys.stdin.fileno())
print(f"Mode: {stat.filemode(st.st_mode)}")
print(f"Is CharDevice: {stat.S_ISCHR(st.st_mode)}")
print(f"Is FIFO/Pipe: {stat.S_ISFIFO(st.st_mode)}")
print(f"Is Socket: {stat.S_ISSOCK(st.st_mode)}")

# Test if stdin would block
print("Testing if stdin blocks...")
ready, _, _ = select.select([sys.stdin], [], [], 2.0)
if ready:
    print("Stdin had data available")
else:
    print("Stdin blocked for 2+ seconds")
jimweller · 10 months ago

Sampled a hanging Node.js process using macOS sample tool and confirmed it's blocked in the kevent syscall:

2248 uv__io_poll  (in libuv.1.dylib) + 764
: 2248 kevent  (in libsystem_kernel.dylib) + 8

Out of 2265 samples over ~7 seconds, 2248 (99.25%) were blocked in kevent waiting for stdin I/O that never completes.

Call stack shows:

  • node::SpinEventLoopInternal - Node.js event loop
  • uv_run → uv__io_poll - libuv I/O polling
  • kevent - waiting for stdin file descriptor to become readable

This indicates the stdin socket never closes and never provides data, causing the event loop to block indefinitely on macOS.

github-actions[bot] · 9 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

jimweller · 9 months ago

go version is working quickly on claude code 2.0.76.

github-actions[bot] · 9 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.