{"record":{"id":"5a1e29a0eb9d2e37","repo":"conductor-oss/conductor","slug":"failed-to-check-video-status-message","errorCode":null,"errorMessage":"Failed to check video status: {message}","messagePattern":"Failed to check video status: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/providers/gemini/GeminiVideoModel.java","lineNumber":166,"sourceCode":"                    }\n                }\n\n                metadata.setStatus(\"COMPLETED\");\n                log.info(\n                        \"Gemini Veo video completed: operation={}, videos={}\",\n                        jobId,\n                        generations.size());\n                return new VideoResponse(generations, metadata);\n\n            } else {\n                metadata.setStatus(\"PROCESSING\");\n                log.debug(\"Gemini Veo video in progress: operation={}\", jobId);\n                return new VideoResponse(List.of(), metadata);\n            }\n\n        } catch (Exception e) {\n            log.error(\"Failed to check Gemini Veo video status for operation {}\", jobId, e);\n            throw new RuntimeException(\"Failed to check video status: \" + e.getMessage(), e);\n        }\n    }\n\n    private byte[] downloadFromUrl(String url) {\n        okhttp3.Request request = new okhttp3.Request.Builder().url(url).get().build();\n        try (okhttp3.Response response = httpClient.newCall(request).execute()) {\n            if (response.body() == null) {\n                throw new RuntimeException(\"Empty response downloading image from \" + url);\n            }\n            return response.body().bytes();\n        } catch (RuntimeException e) {\n            throw e;\n        } catch (Exception e) {\n            throw new RuntimeException(\"Failed to download image from \" + url, e);\n        }\n    }\n}\n","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/providers/gemini/GeminiVideoModel.java#L148-L184","documentation":"GeminiVideoModel.checkStatus() catches any Exception during the Veo video operation polling (api.getVideosOperation) and wraps it. The operation name (jobId) is included in the error log. The original exception is preserved as the cause. This covers failures when polling a previously-submitted long-running video generation operation.","triggerScenarios":"The api.getVideosOperation(jobId) call fails: the operation name is invalid or malformed, the operation has expired or been garbage-collected by Google, API key changed since job submission, network failure during polling, or the Vertex AI project/location doesn't match the one used for submission.","commonSituations":"Polling a job ID from a previous Conductor restart where credentials changed. Job ID truncated or corrupted in storage. Operation expired (Veo operations have a retention window). Network blip during a polling loop. Different API key used for submission vs. polling.","solutions":["Inspect getCause() for the specific failure.","Verify the jobId/operation name is complete and matches what was returned from the initial call() submission.","Ensure the same API key / Vertex AI credentials and project are used for both submission (call) and polling (checkStatus).","Handle expired operations gracefully — if the operation is gone, re-submit the generation.","Implement retry with backoff for transient polling failures."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Validate operation name before polling\nvoid validateOperationName(String jobId) {\n    if (jobId == null || jobId.isBlank()) {\n        throw new IllegalArgumentException(\"Job ID / operation name is required\");\n    }\n    // Veo operation names follow a predictable pattern\n    if (!jobId.startsWith(\"operations/\")) {\n        throw new IllegalArgumentException(\n            \"Invalid Veo operation name: \" + jobId\n            + \" — expected format: operations/...\");\n    }\n}","typeGuard":null,"tryCatchPattern":"// Retry polling with backoff for transient failures\nfor (int attempt = 0; attempt < 3; attempt++) {\n    try {\n        return videoModel.checkStatus(jobId);\n    } catch (RuntimeException e) {\n        if (attempt < 2 && isTransient(e.getCause())) {\n            Thread.sleep((long) Math.pow(2, attempt) * 5000);\n            continue;\n        }\n        throw new RuntimeException(\n            \"Failed to poll Veo operation \" + jobId\n            + \" — verify credentials match submission\", e);\n    }\n}","preventionTips":["Use the same API key / Vertex AI credentials for both submission (call) and polling (checkStatus).","Verify the operation name is complete — truncation in storage corrupts it.","Handle expired operations gracefully — if polling fails permanently, re-submit the job.","Implement retry with backoff for transient polling failures.","Store the jobId immediately after call() returns to avoid losing it."],"tags":["gemini","video","veo","api-error","polling","async"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}