{"record":{"id":"04fc87ec285c3013","repo":"apache/beam","slug":"init-hooks-have-already-run-register-function-during-init","errorCode":null,"errorMessage":"Init hooks have already run. Register function during init() instead.","messagePattern":"Init hooks have already run\\. Register function during init\\(\\) instead\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/symbols.go","lineNumber":78,"sourceCode":"\tif r, err := symtab.New(os.Args[0]); err == nil {\n\t\treturn r\n\t}\n\treturn failResolver(false)\n}\n\n// SymbolResolver resolves a symbol to an unsafe address.\ntype SymbolResolver interface {\n\t// Sym2Addr returns the address pointer for a given symbol.\n\tSym2Addr(string) (uintptr, error)\n}\n\n// RegisterFunction allows function registration. It is beneficial for performance\n// and is needed for functions -- such as custom coders -- serialized during unit\n// tests, where the underlying symbol table is not available. It should be called\n// in `init()` only.\nfunc RegisterFunction(fn any) {\n\tif initialized {\n\t\tpanic(\"Init hooks have already run. Register function during init() instead.\")\n\t}\n\n\tkey := reflectx.FunctionName(fn)\n\t// If the function was registered already, the key and value will be the same anyway.\n\tcache[key] = fn\n}\n\n// RegisterFunctionWithName registers fn under the given name,\n// overriding the automatically derived symbol name. This is necessary\n// for closures produced by Go generic functions where multiple type\n// instantiations generate closures with the same compiler-assigned\n// name (e.g. \"pkg.Func[...].func1\") — without distinct names the\n// last registration wins and cross-worker deserialization resolves\n// the wrong function.\n//\n// Callers must ensure that name is stable across process invocations\n// (pipeline driver and workers must agree). A typical choice is\n// \"<package>.<GenericFunc>[<TypeParam>].enc\".","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/symbols.go#L60-L96","documentation":"runtime.RegisterFunction caches a function value by its reflect-based symbol name so serialized pipelines can resolve it in workers where the symbol table is unavailable. Registration is only safe before beam.Init() runs; afterward the cache is considered frozen and the library panics to prevent nondeterministic late registration.","triggerScenarios":"Calling runtime.RegisterFunction(fn) (directly or via RegisterDoFn/RegisterCoder wrappers) after beam.Init() has executed — e.g. registering coders/DoFns inside main after Init, in a test after TestMain ran Init, or from lazily initialized code.","commonSituations":"Tests that call beam.Init() in TestMain and register custom coders inside individual tests; moving Init to the top of main ahead of init()-time registration; plugins loaded at runtime that try to register symbols.","solutions":["Move all RegisterFunction calls into package init() functions.","Ensure beam.Init() is called only after every package whose init() performs registration is linked/imported.","In tests, register custom coders/functions via init() or separate registration-capable test helpers that run before Init."],"exampleFix":"// before\nfunc main() {\n    beam.Init()\n    runtime.RegisterFunction(myFn) // panics\n}\n// after\nfunc init() {\n    runtime.RegisterFunction(myFn)\n}\nfunc main() {\n    beam.Init()\n}","handlingStrategy":"validation","validationCode":"// ensure call site is a package init() function:\nfunc init() { runtime.RegisterFunction(myFn) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do all symbol registration in init() functions","Import registering packages before main calls beam.Init()","Register coders/DoFns at link time, not at first-use time"],"tags":["go","apache-beam","serialization","registration","panic"],"backgroundTag":"invalid-state-transition","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}