rakyll/hey · critical

call failed

Error message

call failed

What it means

On Windows, hey's high-resolution timing uses QueryPerformanceFrequency via syscall.Syscall. The Win32 contract is that QueryPerformanceFrequency returns nonzero on success; if it returns 0 the call failed and this code panics with "call failed" because the QPC frequency is essential for the now() clock and there is no meaningful fallback. Because it is a panic (not an error return), the whole process aborts.

Source

Thrown at requester/now_windows.go:44

	syscall.Syscall(queryPerformanceCounterProc.Addr(), 1, uintptr(unsafe.Pointer(&now)), 0, 0)
	return time.Duration(now) * time.Second / (time.Duration(qpcFrequency) * time.Nanosecond)
}

// precision timing
var (
	modkernel32                   = syscall.NewLazyDLL("kernel32.dll")
	queryPerformanceFrequencyProc = modkernel32.NewProc("QueryPerformanceFrequency")
	queryPerformanceCounterProc   = modkernel32.NewProc("QueryPerformanceCounter")

	qpcFrequency = queryPerformanceFrequency()
)

// queryPerformanceFrequency returns frequency in ticks per second
func queryPerformanceFrequency() int64 {
	var freq int64
	r1, _, _ := syscall.Syscall(queryPerformanceFrequencyProc.Addr(), 1, uintptr(unsafe.Pointer(&freq)), 0, 0)
	if r1 == 0 {
		panic("call failed")
	}
	return freq
}

View on GitHub (pinned to 5626f79b86)

Solutions

  1. Verify the Windows version supports QueryPerformanceFrequency (Windows 2000+ / XP+); patch the OS to a supported build.
  2. Re-run on real hardware or a properly configured VM — check hypervisor/virtualization settings, as broken HAL or paravirtualized clocks can fail the syscall.
  3. Update Windows system drivers/HAL or run sfc /scannow to repair system files that may be corrupting kernel time services.
  4. Rebuild hey for the correct platform (GOOS=windows) so the lazy proc lookup binds to the real kernel32.QueryPerformanceFrequency rather than a stub.
  5. If maintaining the library, replace the panic with a non-fatal fallback clock (e.g. time.Now) so a QPC failure degrades timing resolution instead of crashing.

Example fix

// before
func queryPerformanceFrequency() int64 {
	var freq int64
	r1, _, _ := syscall.Syscall(queryPerformanceFrequencyProc.Addr(), 1, uintptr(unsafe.Pointer(&freq)), 0, 0)
	if r1 == 0 {
		panic("call failed")
	}
	return freq
}

// after
func queryPerformanceFrequency() int64 {
	var freq int64
	r1, _, err := syscall.SyscallN(queryPerformanceFrequencyProc.Addr(), uintptr(unsafe.Pointer(&freq)))
	if r1 == 0 {
		freq = int64(time.Second) // safe fallback: 1 tick == 1 ns via time.Now clock
		_ = err
	}
	return freq
}
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-flight check on Windows before running the load test:
// ensure the process can initialize QPC (Go: golang.org/x/sys/windows)
func qpcAvailable() bool {
	var freq int64
	// QueryPerformanceFrequency documented to succeed on Win2000+; verify on target host
	return windows.QueryPerformanceFrequency(&freq) == nil && freq > 0
}

Try / catch

// Wrap the load-test run so a QPC panic is converted to a diagnosable failure:
func runSafe(run func()) {
	defer func() {
		if r := recover(); r != nil {
			if fmt.Sprint(r) == "call failed" {
				fmt.Fprintln(os.Stderr, "QueryPerformanceFrequency failed on this Windows host; update OS/VM or use a non-Windows host")
				os.Exit(1)
			}
			panic(r)
		}
	}()
	run()
}

Prevention

When it happens

Trigger: queryPerformanceFrequency calls syscall.Syscall on queryPerformanceFrequencyProc and the underlying Win32 API returns r1 == 0 — i.e. Windows itself failed to report the performance-counter frequency. Note the panic lives in queryPerformanceFrequency, which qpcFrequency calls lazily when the requester builds its clock.

Common situations: Running a build on an unsupported or broken Windows version where QueryPerformanceFrequency is unavailable (extremely old Windows without QPC support), corrupted system state/driver issues affecting the HAL, or running under an emulation/virtualization layer where the syscall fails; also a mismatched proc address if the syscall.NewLazyDLL lookup silently returned a stub.


AI-assisted analysis of rakyll/hey@5626f79b86 (2026-09-02). Data as JSON: /api/errors/5e812eaab66b36e6. Report an issue: GitHub.