golang/go · error

GOCACHEPROG program closed unexpectedly

Error message

GOCACHEPROG program closed unexpectedly

What it means

When using GOCACHEPROG (an external cache program invoked as a child process), the send() function writes a request and waits for a response on a channel. If the channel receives nil, the output reader goroutine has exited, meaning the child process closed its output pipe before responding. The sentinel error errCacheprogClosed is returned to signal that the cache program is no longer running.

Source

Thrown at src/cmd/go/internal/cache/prog.go:183

				inFlight := len(c.inFlight)
				c.mu.Unlock()
				base.Fatalf("GOCACHEPROG exited pre-Close with %v pending requests", inFlight)
			}
			base.Fatalf("error reading JSON from GOCACHEPROG: %v", err)
		}
		c.mu.Lock()
		ch, ok := c.inFlight[res.ID]
		delete(c.inFlight, res.ID)
		c.mu.Unlock()
		if ok {
			ch <- res
		} else {
			base.Fatalf("GOCACHEPROG sent response for unknown request ID %v", res.ID)
		}
	}
}

var errCacheprogClosed = errors.New("GOCACHEPROG program closed unexpectedly")

func (c *ProgCache) send(ctx context.Context, req *cacheprog.Request) (*cacheprog.Response, error) {
	resc := make(chan *cacheprog.Response, 1)
	if err := c.writeToChild(req, resc); err != nil {
		return nil, err
	}
	select {
	case res := <-resc:
		if res == nil {
			return nil, errCacheprogClosed
		}
		if res.Err != "" {
			return nil, errors.New(res.Err)
		}
		return res, nil
	case <-ctx.Done():
		return nil, ctx.Err()
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Check if the GOCACHEPROG program binary exists and is executable
  2. Run the GOCACHEPROG program standalone to observe its error output or crash reason
  3. Check system logs (dmesg, journalctl) for OOM kills or signal-based termination
  4. Temporarily unset GOCACHEPROG to fall back to the default disk cache and isolate the issue
  5. Update or reinstall the cache program to ensure compatibility with your Go version

Example fix

// before: GOCACHEPROG program crashes silently
// $ GOCACHEPROG=my-cache-prog go build ./...
// # fails: GOCACHEPROG program closed unexpectedly

// after: debug the program, then either fix or bypass
// $ my-cache-prog 2>&1  # run standalone to see errors
// $ dmesg | grep -i oom  # check for OOM kill
// $ unset GOCACHEPROG && go build ./...  # bypass to confirm
// $ GOCACHEPROG=fixed-cache-prog go build ./...  # use fixed version
Defensive patterns

Strategy: fallback

Validate before calling

// Before starting a build with GOCACHEPROG, verify the program is alive.
import "os/exec"

func validateCacheProg(progBin string) error {
    if progBin == "" {
        return nil // no GOCACHEPROG, using default disk cache
    }
    // Check the binary exists and is executable
    info, err := os.Stat(progBin)
    if err != nil {
        return fmt.Errorf("GOCACHEPROG binary not found: %v", err)
    }
    if info.Mode()&0111 == 0 {
        return fmt.Errorf("GOCACHEPROG binary is not executable: %s", progBin)
    }
    return nil
}

Type guard

func isCacheprogClosed(err error) bool {
    return err != nil && strings.Contains(err.Error(), "GOCACHEPROG program closed unexpectedly")
}

Try / catch

// Fallback from GOCACHEPROG to disk cache:
//
// err := buildWithCache()
// if isCacheprogClosed(err) {
//     // The cache program died — fall back to disk cache
//     os.Unsetenv("GOCACHEPROG")
//     err = buildWithCache() // retry with default disk cache
// }
//
// Shell-level fallback:
// $ GOCACHEPROG=myprog go build ./... || \
//   (unset GOCACHEPROG && go build ./...)

Prevention

When it happens

Trigger: ProgCache.send() calls writeToChild to queue a request, then receives nil from the response channel (resc). A nil value means the reader goroutine that feeds resc has terminated — the child process's stdout/pipe closed.

Common situations: The GOCACHEPROG program crashed or exited unexpectedly; the program hit a fatal error and terminated; the process was killed by the OS (OOM killer, cgroup limits); the program's binary is broken, missing, or incompatible with the current platform; the program received a signal.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/92200a0e8f4673e0. Report an issue: GitHub.