{"record":{"id":"352e60473f471039","repo":"PaddlePaddle/PaddleOCR","slug":"initialization-did-not-complete-call-initialize","errorCode":null,"errorMessage":"Initialization did not complete. Call initialize() first.","messagePattern":"Initialization did not complete\\. Call initialize\\(\\) first\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"paddleocr-js/packages/core/src/pipelines/ocr/core.ts","lineNumber":209,"sourceCode":"  }\n\n  getModelConfig(): OcrModelConfig {\n    return this.modelConfig;\n  }\n\n  async predict(input: unknown, params: OcrRuntimeParamsInput = {}): Promise<OcrResult[]> {\n    if (!this.sourceToMat) {\n      throw new Error(\"PaddleOCR source adapter is not configured.\");\n    }\n    if (!this.detModel || !this.recModel || !this.cv || !this.ort) {\n      await this.initialize();\n    }\n\n    const cv = this.cv;\n    const detModel = this.detModel;\n    const recModel = this.recModel;\n    if (!cv || !detModel || !recModel) {\n      throw new Error(\"Initialization did not complete. Call initialize() first.\");\n    }\n\n    const sources = Array.isArray(input) ? input : [input];\n    const sourceToMat = this.sourceToMat;\n    const pipelineBatchSize = Math.max(1, Math.floor(this.pipelineConfig.pipelineBatchSize) || 1);\n    const sourceBatches = chunkArray(sources, pipelineBatchSize);\n\n    const totalStart = nowMs();\n    const resolved = getOcrRuntimeParams(this.modelConfig, this.runtimeDefaults, params);\n\n    let sumDetMs = 0;\n    let sumRecMs = 0;\n    const partials: Array<{\n      image: { width: number; height: number };\n      items: OcrResultItem[];\n      detectedBoxes: number;\n      recognizedCount: number;\n    }> = [];","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr-js/packages/core/src/pipelines/ocr/core.ts#L191-L227","documentation":"Thrown by OcrPipelineRunner.predict() after it lazily awaited initialize() yet detModel, recModel, or the cv/ort handles are still missing. The guard exists because initialize() can return without fully populating state (a swallowed failure, an aborted init, or a derived class overriding initialize incompletely). It distinguishes 'not initialized yet' (auto-fixed) from 'initialization ran but did not complete' (this error).","triggerScenarios":"Calling predict() when a previous initialize() failed partway (e.g. det model loaded, rec download threw) and the failure was caught and ignored; a subclass overriding initialize() without calling super or without assigning all four fields; concurrent predict() calls where one init path errored.","commonSituations":"Wrapping initialize() in a try-catch that logs-and-continues, leaving the runner half-initialized; intermittent model fetch failures in CI; disposed/re-initialized runners where ort or cv was torn down but detModel reference survived.","solutions":["Call and await initialize() explicitly, and let its errors propagate — do not catch-and-continue","Check getInitializationSummary() after init to confirm all models and backends came up","If initialization failed, re-create the runner (or re-run initialize) instead of retrying predict on the half-built one","For subclass authors: ensure initialize() assigns detModel, recModel, cv, and ort before resolving"],"exampleFix":"// before\nrunner.initialize().catch(e => console.warn(e)); // swallowed\nawait runner.predict(img); // throws: initialization did not complete\n\n// after\ntry { await runner.initialize(); } catch (e) { /* report and stop */ throw e; }\nawait runner.predict(img);","handlingStrategy":"retry","validationCode":"await runner.initialize(); // let errors propagate\nconst summary = runner.getInitializationSummary();\nif (!summary?.detModel || !summary?.recModel) {\n  throw new Error(\"Initialization incomplete — do not call predict\");\n}","typeGuard":"function isRunnerInitialized(runner: { detModel: unknown; recModel: unknown; cv: unknown; ort: unknown }): boolean {\n  return Boolean(runner.detModel && runner.recModel && runner.cv && runner.ort);\n}","tryCatchPattern":"try { await runner.predict(input); } catch (e) {\n  if (e instanceof Error && /Initialization did not complete/.test(e.message)) {\n    await runner.initialize(); // fresh, full init; then retry predict once\n    await runner.predict(input);\n  } else throw e;\n}","preventionTips":["Await initialize() explicitly once and let failures stop the flow — never catch-and-continue","Verify getInitializationSummary() reports all models before first predict","Recreate the runner after a failed init rather than reusing half-built state"],"tags":["paddleocr","lifecycle","async-init","error-swallowing"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}