diff --git a/admin-lehrer/components/ocr-pipeline/StepWordRecognition.tsx b/admin-lehrer/components/ocr-pipeline/StepWordRecognition.tsx index 1d519d4..75768a5 100644 --- a/admin-lehrer/components/ocr-pipeline/StepWordRecognition.tsx +++ b/admin-lehrer/components/ocr-pipeline/StepWordRecognition.tsx @@ -105,12 +105,24 @@ export function StepWordRecognition({ sessionId, onNext, goToStep }: StepWordRec setGridResult(null) try { - const res = await fetch( - `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/words?stream=true&engine=${eng}&pronunciation=${pronunciation}`, - { method: 'POST' }, - ) - if (!res.ok) { - const err = await res.json().catch(() => ({ detail: res.statusText })) + // Retry once if initial request fails (e.g. after container restart, + // session cache may not be warm yet when navigating via wizard) + let res: Response | null = null + for (let attempt = 0; attempt < 2; attempt++) { + res = await fetch( + `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/words?stream=true&engine=${eng}&pronunciation=${pronunciation}`, + { method: 'POST' }, + ) + if (res.ok) break + if (attempt === 0 && (res.status === 400 || res.status === 404)) { + // Wait briefly for cache to warm up, then retry + await new Promise(r => setTimeout(r, 2000)) + continue + } + break + } + if (!res || !res.ok) { + const err = await res?.json().catch(() => ({ detail: res?.statusText })) || { detail: 'Worterkennung fehlgeschlagen' } throw new Error(err.detail || 'Worterkennung fehlgeschlagen') } diff --git a/klausur-service/backend/ocr_pipeline_api.py b/klausur-service/backend/ocr_pipeline_api.py index bd641b6..82e745b 100644 --- a/klausur-service/backend/ocr_pipeline_api.py +++ b/klausur-service/backend/ocr_pipeline_api.py @@ -1204,11 +1204,14 @@ async def detect_words( stream: false (default) for JSON response, true for SSE streaming """ if session_id not in _cache: + logger.info("detect_words: session %s not in cache, loading from DB", session_id) await _load_session_to_cache(session_id) cached = _get_cached(session_id) dewarped_bgr = cached.get("dewarped_bgr") if dewarped_bgr is None: + logger.warning("detect_words: dewarped_bgr is None for session %s (cache keys: %s)", + session_id, [k for k in cached.keys() if k.endswith('_bgr')]) raise HTTPException(status_code=400, detail="Dewarp must be completed before word detection") session = await get_session_db(session_id)