grpc/grpc-go · error

failed to create temp file: %v

Error message

failed to create temp file: %v

What it means

binarylog.NewTempFileSink() creates a temporary file under /tmp via os.CreateTemp("/tmp", "grpcgo_binarylog_*.txt") to serve as a binary log destination (sink.go:63). If the OS call fails, the underlying error is wrapped and returned. The sink is used by the binary logging feature (env vars GRPC_BINARY_LOG_FILTER / GRPC_BINARY_LOG_LOGGER).

Source

Thrown at binarylog/sink.go:65

	// is not specified, but should have sufficient information to rebuild the
	// entry. Some options are: proto bytes, or proto json.
	//
	// Note this function needs to be thread-safe.
	Write(*binlogpb.GrpcLogEntry) error
	// Close closes this sink and cleans up resources (e.g. the flushing
	// goroutine).
	Close() error
}

// NewTempFileSink creates a temp file and returns a Sink that writes to this
// file.
func NewTempFileSink() (Sink, error) {
	// Two other options to replace this function:
	// 1. take filename as input.
	// 2. export NewBufferedSink().
	tempFile, err := os.CreateTemp("/tmp", "grpcgo_binarylog_*.txt")
	if err != nil {
		return nil, fmt.Errorf("failed to create temp file: %v", err)
	}
	return iblog.NewBufferedSink(tempFile), nil
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Ensure /tmp exists and is writable by the process, or remount it read-write in the container.
  2. Free disk space or raise the file-descriptor / inode limits (ulimit -n).
  3. Switch to a custom Sink implementation (implement the Sink interface) writing to a path you control instead of NewTempFileSink.

Example fix

// before
sink, err := binarylog.NewTempFileSink()
// after (write to a controlled path)
f, err := os.OpenFile("/var/log/grpc/binlog.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil { return err }
sink := iblog.NewBufferedSink(f)
Defensive patterns

Strategy: try-catch

Validate before calling

// Check /tmp writability before relying on NewTempFileSink.
func tmpWritable() bool {
    f, err := os.CreateTemp("/tmp", "probe_*")
    if err != nil { return false }
    f.Close(); os.Remove(f.Name()); return true
}

Try / catch

sink, err := binarylog.NewTempFileSink()
if err != nil {
    log.Printf("temp sink unavailable (%v); falling back to custom sink", err)
    f, _ := os.OpenFile("/var/log/grpc/binlog.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
    sink = iblog.NewBufferedSink(f)
}

Prevention

When it happens

Trigger: Calling binarylog.NewTempFileSink() when /tmp does not exist, is not writable, is full (ENOSPC), or the process lacks permissions. Also when the open-file / inode limit is exhausted.

Common situations: Running in a hardened container or read-only filesystem where /tmp is missing or mounted read-only; a full disk; exceeding the per-process file descriptor limit; SELinux/AppArmor denying temp file creation.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/a3d7c3cd0896979e. Report an issue: GitHub.