apache/beam · error
RegisterHeapCaptureHook
Error message
RegisterHeapCaptureHook: %s registered twice
What it means
RegisterHeapCaptureHook registers a heap-profile CaptureHookFactory in heapCaptureHookRegistry and panics on duplicate names. The fail-fast design catches conflicting registrations at process startup rather than producing ambiguous profiling output later.
Solutions
- Grep for RegisterHeapCaptureHook with the offending name and remove the duplicate call.
- Centralize registration in one package's init and blank-import it where needed.
- Run go mod graph/tidy to remove duplicate versions of the hook package.
- Guard dynamic registration with sync.Once or an existence check.
Example fix
// before
func init() { perf.RegisterHeapCaptureHook("heap", h) }
func main() { perf.RegisterHeapCaptureHook("heap", h) } // panics
// after
var heapOnce sync.Once
func registerHeapHook() { heapOnce.Do(func() { perf.RegisterHeapCaptureHook("heap", h) }) } Defensive patterns
Strategy: validation
Validate before calling
if _, exists := heapRegistered["heap"]; !exists {
perf.RegisterHeapCaptureHook("heap", myFactory)
} Try / catch
func registerHeap(name string, f perf.CaptureHookFactory) {
defer func() {
if r := recover(); r != nil {
log.Printf("heap hook %q already registered: %v", name, r)
}
}()
perf.RegisterHeapCaptureHook(name, f)
} Prevention
- Register heap hooks once via a single package init.
- Use sync.Once around registration in shared/test helpers.
- Audit go.mod for duplicate versions of the hook package.
- Keep the registration list in one place and reference it from tests.
When it happens
Trigger: Calling perf.RegisterHeapCaptureHook(name, factory) when the name already exists in heapCaptureHookRegistry — duplicate init() calls, registering in both test bootstrap and application init, or two module versions of the same hook package linked into one binary.
Common situations: Multiple heap profiling hooks with the same identifier from different packages; repeated test suite initialization in one process; dependency upgrades introducing a second copy of the hook package.
Related errors
- RegisterProfCaptureHook
- RegisterTraceCaptureHook
- Beam has not been initialized. Call beam.Init() before…
- Init hooks have already run. Register hook during init()…
- while executing Up for
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/5b71884d58dceeba.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/x/hooks/perf/perf.go:210
// Rewrite the registration with the current arguments
enabledTraceCaptureHooks[i] = enc
hooks.EnableHook("trace", enabledTraceCaptureHooks...)
return
}
}
enabledTraceCaptureHooks = append(enabledTraceCaptureHooks, enc)
hooks.EnableHook("trace", enabledTraceCaptureHooks...)
}
var heapCaptureHookRegistry = make(map[string]CaptureHookFactory)
var enabledHeapCaptureHooks []string
// RegisterHeapCaptureHook registers a CaptureHookFactory for the
// supplied identifier. It panics if the same identifier is
// registered twice.
func RegisterHeapCaptureHook(name string, c CaptureHookFactory) {
if _, exists := heapCaptureHookRegistry[name]; exists {
panic(fmt.Sprintf("RegisterHeapCaptureHook: %s registered twice", name))
}
heapCaptureHookRegistry[name] = c
}
// EnableHeapCaptureHook actives a registered heap profile capture hook for a given pipeline.
func EnableHeapCaptureHook(name string, opts ...string) {
_, exists := heapCaptureHookRegistry[name]
if !exists {
panic(fmt.Sprintf("EnableHeapCaptureHook: %s not registered", name))
}
enc := hooks.Encode(name, opts)
for i, h := range enabledHeapCaptureHooks {
n, _ := hooks.Decode(h)
if h == n {
// Rewrite the registration with the current arguments
enabledHeapCaptureHooks[i] = encView on GitHub (pinned to 12126d8942)