{"record":{"id":"396c7bd166eaa269","repo":"kataras/iris","slug":"mvc-singleton-called-from-wrong-state-the-api-giv","errorCode":null,"errorMessage":"MVC: Singleton called from wrong state the API gives access to it only `AfterActivation`, report this as bug","messagePattern":"MVC: Singleton called from wrong state the API gives access to it only `AfterActivation`, report this as bug","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mvc/controller.go","lineNumber":323,"sourceCode":"}\n\n// Use registers a middleware for this Controller.\n// It appends one or more handlers to the `BeginHandlers`.\n// It's like the `Party.Use` but specifically\n// for the routes that this controller will register to the targeted `Party`.\nfunc (c *ControllerActivator) Use(handlers ...context.Handler) *ControllerActivator {\n\tc.BeginHandlers = append(c.BeginHandlers, handlers...)\n\treturn c\n}\n\n// Singleton returns new if all incoming clients' requests\n// have the same controller instance.\n// This is done automatically by iris to reduce the creation\n// of a new controller on each request, if the controller doesn't contain\n// any unexported fields and all fields are services-like, static.\nfunc (c *ControllerActivator) Singleton() bool {\n\tif c.injector == nil {\n\t\tpanic(\"MVC: Singleton called from wrong state the API gives access to it only `AfterActivation`, report this as bug\")\n\t}\n\treturn c.injector.Singleton\n}\n\n// DependenciesReadOnly returns a list of dependencies, including the controller's one.\nfunc (c *ControllerActivator) DependenciesReadOnly() []*hero.Dependency {\n\tif c.injector == nil {\n\t\tpanic(\"MVC: DependenciesReadOnly called from wrong state the API gives access to it only `AfterActivation`, report this as bug\")\n\t}\n\n\treturn c.injector.Container.Dependencies\n}\n\n// Dependencies returns a value which can manage the controller's dependencies.\nfunc (c *ControllerActivator) Dependencies() *hero.Container {\n\treturn c.app.container // although the controller's one are: c.injector.Container\n}\n","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/mvc/controller.go#L305-L341","documentation":"ControllerActivator.Singleton reads the injector's Singleton flag, but the injector is only created after the controller is activated (its dependencies resolved). Calling Singleton before activation means the framework is being used out of order, so it panics and asks you to report it as a bug if reached through the documented AfterActivation flow.","triggerScenarios":"Calling activator.Singleton() right after mvc.New(app).Handle (or inside a controller constructor) before AfterActivation has run, e.g. during Configure-time reflection on a controller that has no activation yet.","commonSituations":"Custom bootstrap code inspecting controller metadata before app.Listen/AfterActivation, tests that grab the activator and query it immediately, or plugin code hooking into MVC setup too early.","solutions":["Move the Singleton() call into an AfterActivation callback, e.g. mvcApp.AfterActivation(func(a *mvc.Activation) { _ = a.Singleton() }).","If you need the flag earlier, resolve dependencies first by calling activator.Activate(nil) or rely on Activate/Handlers flow before inspecting state.","If it panics even inside AfterActivation, report it to the iris repo as the message instructs."],"exampleFix":"// before\nm := mvc.New(app)\nm.Handle(new(UsersController))\nisSingleton := m.Activator.Singleton() // panics: injector nil\n// after\nm := mvc.New(app)\nm.Handle(new(UsersController))\nm.AfterActivation(func(a *mvc.Activation) {\n\t_ = a.Singleton() // safe here\n})","handlingStrategy":"validation","validationCode":"// Only read singleton state inside AfterActivation:\nmvcApp.AfterActivation(func(a *mvc.Activation) {\n\t_ = a.Singleton()\n})","typeGuard":"// Go cannot nil-check private fields; guard by lifecycle:\n// safe only when invoked from AfterActivation callbacks.","tryCatchPattern":"defer func() {\n\tif r := recover(); r != nil {\n\t\tlog.Printf(\"MVC singleton state error: %v\", r)\n\t}\n}()","preventionTips":["Treat ControllerActivator accessors as post-activation APIs only.","Inspect MVC metadata exclusively in AfterActivation hooks.","Write a boot-time smoke test that walks activation lifecycle."],"tags":["panic","mvc","lifecycle","wrong-state"],"backgroundTag":"api-called-before-initialized","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}