{"record":{"id":"e26f14f020bc1238","repo":"docling-project/docling","slug":"engine-not-initialized-call-initialize-first","errorCode":null,"errorMessage":"Engine not initialized. Call initialize() first.","messagePattern":"Engine not initialized\\. Call initialize\\(\\) first\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"docling/models/inference_engines/image_classification/api_kserve_v2_engine.py","lineNumber":150,"sourceCode":"                grpc_channel_args=list(self.options.grpc_channel_args),\n            )\n        self._input_name, self._output_name = self._resolve_tensor_names()\n\n        self._initialized = True\n        _log.info(\n            \"KServe v2 image-classification engine ready (input=%s, output=%s)\",\n            self._input_name,\n            self._output_name,\n        )\n\n    def predict_batch(\n        self, input_batch: List[ImageClassificationEngineInput]\n    ) -> List[ImageClassificationEngineOutput]:\n        \"\"\"Run inference on a batch of images against a KServe v2 endpoint.\"\"\"\n        if not input_batch:\n            return []\n        if not self._initialized:\n            raise RuntimeError(\"Engine not initialized. Call initialize() first.\")\n\n        # Type narrowing: _initialized guarantees these are non-None\n        assert self._processor is not None\n        assert self._kserve_client is not None\n        assert self._input_name is not None\n        assert self._output_name is not None\n\n        images = [item.image.convert(\"RGB\") for item in input_batch]\n        processed_inputs = self._processor(images=images, return_tensors=\"np\")\n        pixel_values = np.asarray(processed_inputs[\"pixel_values\"])\n\n        outputs = self._kserve_client.infer(\n            inputs={self._input_name: pixel_values},\n            output_names=[self._output_name],\n            request_parameters=self.options.request_parameters,\n        )\n        try:\n            logits_batch = outputs[self._output_name]","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/models/inference_engines/image_classification/api_kserve_v2_engine.py#L132-L168","documentation":"predict_batch was called on the ApiKserveV2 engine before successful initialization. The engine tracks an _initialized flag set at the end of initialize(); inference before that would dereference a None client/processor, so it fails fast with this guard. Unlike the metadata errors, this is purely a call-order problem on the client side.","triggerScenarios":"Calling engine.predict_batch(input_batch) on ApiKserveV2ImageClassificationEngine when _initialized is False — i.e. initialize() never ran, or it raised partway (client, processor, or tensor-name resolution failed) and the exception was caught upstream.","commonSituations":"Swallowing an initialize() exception in retry logic and continuing to predict; reusing an engine after a failed re-initialization; integrating the engine in a custom runner that skips the init step.","solutions":["Call engine.initialize() once and let failures propagate — do not catch-and-continue.","If initialization failed, fix the root cause (endpoint reachability, enable_remote_services, metadata) before predicting.","Track engine state explicitly: initialize immediately after construction, before any predict_batch call."],"exampleFix":"# before\ntry:\n    engine.initialize()\nexcept Exception:\n    pass  # swallowed\nengine.predict_batch(batch)  # RuntimeError\n\n# after\nengine.initialize()  # failures surface here\nengine.predict_batch(batch)","handlingStrategy":"validation","validationCode":"if not engine._initialized:\n    engine.initialize()  # or raise, depending on your lifecycle policy","typeGuard":null,"tryCatchPattern":"try:\n    engine.predict_batch(batch)\nexcept RuntimeError as e:\n    if \"not initialized\" in str(e):\n        engine.initialize()\n        engine.predict_batch(batch)\n    else:\n        raise","preventionTips":["Enforce construct -> initialize -> predict ordering in a small wrapper class.","Do not swallow initialize() exceptions in retry loops.","Recreate engines after failures instead of reusing half-initialized instances."],"tags":["lifecycle","initialization","kserve","call-order"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}