{"record":{"id":"a15e918326c0f62e","repo":"apache/beam","slug":"init-hooks-have-already-run-register-hook-during-init","errorCode":null,"errorMessage":"Init hooks have already run. Register hook during init() instead.","messagePattern":"Init hooks have already run\\. Register hook during init\\(\\) instead\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/init.go","lineNumber":31,"sourceCode":"// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package runtime contains runtime hooks and utilities for pipeline options\n// and type registration. Most functionality done in init and hence is\n// available both during pipeline-submission and at runtime.\npackage runtime\n\nvar (\n\thooks       []func()\n\tinitialized bool\n)\n\n// RegisterInit registers an Init hook. Hooks are expected to be able to\n// figure out whether they apply on their own, notably if invoked in a remote\n// execution environment. They are all executed regardless of the runner.\nfunc RegisterInit(hook func()) {\n\tif initialized {\n\t\tpanic(\"Init hooks have already run. Register hook during init() instead.\")\n\t}\n\n\thooks = append(hooks, hook)\n}\n\n// Init is the hook that all user code must call after flags processing and\n// other static initialization, for now.\nfunc Init() {\n\tinitialized = true\n\tfor _, hook := range hooks {\n\t\thook()\n\t}\n}\n\n// Initialized exposes the initialization status for runners.\nfunc Initialized() bool {\n\treturn initialized\n}","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/init.go#L13-L49","documentation":"runtime.RegisterInit queues hooks that run once when beam.Init() executes; after Init has run, the hooks slice is frozen (initialized=true). Registering later would silently never run, so the library panics to force registration in init() time.","triggerScenarios":"Calling runtime.RegisterInit(func(){...}) from normal program flow (a test's Setup, a handler, main after beam.Init()) rather than from a package init() function.","commonSituations":"Moving beam.Init() earlier in main so it precedes registration; a lazily-imported package whose registration code runs post-Init; tests that call beam.Init() in TestMain and then register hooks in individual tests.","solutions":["Move the RegisterInit call into a package init() function so it runs before beam.Init().","If you cannot use init(), ensure RegisterInit executes before any call to beam.Init() in main.","Restructure so the hook's work happens after Init via a different mechanism (e.g. call the function directly after Init)."],"exampleFix":"// before\nfunc main() {\n    beam.Init()\n    runtime.RegisterInit(myHook) // panics\n}\n// after\nfunc init() {\n    runtime.RegisterInit(myHook)\n}\nfunc main() {\n    beam.Init()\n}","handlingStrategy":"validation","validationCode":"// call only from package init(), before beam.Init()\nfunc init() { runtime.RegisterInit(myHook) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register all Init hooks in package init() functions","Call beam.Init() exactly once, as late as reasonable in main","Never register hooks from tests that run after TestMain's beam.Init()"],"tags":["go","apache-beam","initialization","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-20T03:17:13.778Z"}