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
- Verify the Windows version supports QueryPerformanceFrequency (Windows 2000+ / XP+); patch the OS to a supported build.
- Re-run on real hardware or a properly configured VM — check hypervisor/virtualization settings, as broken HAL or paravirtualized clocks can fail the syscall.
- Update Windows system drivers/HAL or run sfc /scannow to repair system files that may be corrupting kernel time services.
- Rebuild hey for the correct platform (GOOS=windows) so the lazy proc lookup binds to the real kernel32.QueryPerformanceFrequency rather than a stub.
- 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
- Run hey on a supported, patched Windows version (or Linux/macOS) — QPC failure indicates an OS/HAL problem, not a usage error.
- Avoid broken paravirtualized clocks: configure the VM with a reliable time source before load testing.
- Pin builds per-platform so GOOS/GOARCH always match the host and lazy DLL bindings resolve to real kernel32 exports.
- Monitor for the panic message 'call failed' in CI on Windows runners and fall back to a non-Windows runner.
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.