{"record":{"id":"776ad83f0bd754c4","repo":"invoke-ai/InvokeAI","slug":"profiler-not-initialized-call-start-first","errorCode":null,"errorMessage":"Profiler not initialized. Call start() first.","messagePattern":"Profiler not initialized\\. Call start\\(\\) first\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"invokeai/app/util/profiler.py","lineNumber":56,"sourceCode":"        self._output_dir.mkdir(parents=True, exist_ok=True)\n        self._profiler: Optional[cProfile.Profile] = None\n        self._prefix = prefix\n\n        self.profile_id: Optional[str] = None\n\n    def start(self, profile_id: str) -> None:\n        if self._profiler:\n            self.stop()\n\n        self.profile_id = profile_id\n\n        self._profiler = cProfile.Profile()\n        self._profiler.enable()\n        self._logger.info(f\"Started profiling {self.profile_id}.\")\n\n    def stop(self) -> Path:\n        if not self._profiler:\n            raise RuntimeError(\"Profiler not initialized. Call start() first.\")\n        self._profiler.disable()\n\n        filename = f\"{self._prefix}_{self.profile_id}.prof\" if self._prefix else f\"{self.profile_id}.prof\"\n        path = Path(self._output_dir, filename)\n\n        self._profiler.dump_stats(path)\n        self._logger.info(f\"Stopped profiling, profile dumped to {path}.\")\n        self._profiler = None\n        self.profile_id = None\n\n        return path\n","sourceCodeStart":38,"sourceCodeEnd":68,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/util/profiler.py#L38-L68","documentation":"Profiler.stop() dumps and saves cProfile stats, but only after start() created the internal cProfile.Profile. If stop() is called before start() (or stop() is called twice, since the profiler handle is consumed/cleared), there is nothing to stop and a RuntimeError is raised.","triggerScenarios":"Calling profiler.stop() without a prior start(); calling stop() a second time after the first stop already tore down the profiler handle.","commonSituations":"Exception during profiled work skips start() but a finally/cleanup block still calls stop(); double invocation of stop in shutdown code; constructing Profiler and immediately stopping it in tests.","solutions":["Call start() before stop() and ensure it succeeded","Guard stop() with a check of the profiler state or a flag set by start()","Ensure stop() is only invoked once per profiling session (e.g. idempotent wrapper or flag)","Wrap the profiling block in try/finally so an exception in the measured code still runs start() first / stop() exactly once"],"exampleFix":"// before\nprofiler.stop()  # RuntimeError if never started\n// after\nif profiler._profiler:\n    profiler.stop()\n# or\nprofiler.start()\ntry:\n    run_workload()\nfinally:\n    profiler.stop()","handlingStrategy":"try-catch","validationCode":"if not getattr(profiler, '_profiler', None):\n    profiler.start()","typeGuard":null,"tryCatchPattern":"try:\n    profiler.stop()\nexcept RuntimeError as e:\n    if 'Profiler not initialized' in str(e):\n        pass  # already stopped or never started\n    else:\n        raise","preventionTips":["Wrap measured work in try/finally with stop() only in finally after a successful start()","Track a started flag; make stop idempotent","Never call stop() twice; save the returned stats path once"],"tags":["python","runtimeerror","profiling","lifecycle"],"backgroundTag":"profiler-not-initialized","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}