{"record":{"id":"7aa38172b57d9d00","repo":"conductor-oss/conductor","slug":"failed-to-submit-video-generation-message","errorCode":null,"errorMessage":"Failed to submit video generation: {message}","messagePattern":"Failed to submit video generation: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/providers/gemini/GeminiVideoModel.java","lineNumber":108,"sourceCode":"            GeminiApi.GenerateVideosOperation operation =\n                    api.generateVideos(opts.getModel(), text, inputBytes, inputMime, config);\n\n            String operationName = operation.name();\n\n            log.info(\n                    \"Gemini Veo video job submitted: operation={}, model={}\",\n                    operationName,\n                    opts.getModel());\n\n            VideoResponseMetadata metadata = new VideoResponseMetadata();\n            metadata.setJobId(operationName);\n            metadata.setStatus(\"PROCESSING\");\n\n            return new VideoResponse(List.of(), metadata);\n\n        } catch (Exception e) {\n            log.error(\"Failed to submit Gemini Veo video generation job\", e);\n            throw new RuntimeException(\"Failed to submit video generation: \" + e.getMessage(), e);\n        }\n    }\n\n    @Override\n    public VideoResponse checkStatus(String jobId) {\n        try {\n            GeminiApi.GenerateVideosOperation operation = api.getVideosOperation(jobId);\n\n            VideoResponseMetadata metadata = new VideoResponseMetadata();\n            metadata.setJobId(jobId);\n\n            if (Boolean.TRUE.equals(operation.done())) {\n                // Check for error\n                if (operation.error() != null) {\n                    metadata.setStatus(\"FAILED\");\n                    metadata.setErrorMessage(operation.error().message());\n                    log.error(\"Gemini Veo video failed: operation={}\", jobId);\n                    return new VideoResponse(List.of(), metadata);","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/providers/gemini/GeminiVideoModel.java#L90-L126","documentation":"GeminiVideoModel.call() catches any Exception during the async Veo video generation job submission (api.generateVideos) and wraps it with the cause's message. This is the broadest catch in the class — it covers IOException from the HTTP call, RuntimeException from input parsing, and any other failure. The original exception is preserved as the cause and logged at ERROR level before rethrowing.","triggerScenarios":"The api.generateVideos() call fails: invalid Veo model name, malformed input image (corrupt base64 or unsupported format for image-to-video), API authentication failure, quota exceeded, content policy violation on the prompt, or network failure to the Gemini/Vertex video endpoint.","commonSituations":"Model name not a Veo model (must be 'veo-2.0-generate-001', 'veo-3.0-generate-001', or 'veo-3.1-generate-001' — or the API-key variants). Input image for image-to-video is corrupt or wrong MIME type. Prompt violates content safety. API key not enabled for Veo. Quota for video generation exhausted. Region doesn't support Veo.","solutions":["Inspect getCause() for the specific exception and its message.","Verify the model name is a valid Veo model available in your region/API tier.","For image-to-video: verify the input image is valid PNG/JPEG — test with downloadFromUrl or base64 decode separately first.","Check API key / Vertex AI credentials and quota for the Veo API.","Review the prompt for content that may trigger safety filters."],"exampleFix":"// before\nVideoOptions opts = VideoOptionsBuilder.builder()\n    .model(\"gemini-2.5-flash\") // not a video model\n    .build();\n\n// after\nVideoOptions opts = VideoOptionsBuilder.builder()\n    .model(\"veo-3.0-generate-001\")\n    .build();","handlingStrategy":"try-catch","validationCode":"// Validate Veo video model and input before submitting\nprivate static final Set<String> VEO_MODELS =\n    Set.of(\"veo-2.0-generate-001\", \"veo-3.0-generate-001\", \"veo-3.1-generate-001\");\n\nvoid validateVideoRequest(VideoPrompt prompt) {\n    String model = prompt.getOptions().getModel();\n    if (!VEO_MODELS.contains(model)) {\n        throw new IllegalArgumentException(\n            \"Use a Veo model for Gemini video generation. Got: \" + model);\n    }\n    String img = prompt.getOptions().getInputImage();\n    if (img != null && !img.isBlank()\n            && !(img.startsWith(\"data:\") || img.startsWith(\"http\")\n                 || img.matches(\"^[A-Za-z0-9+/=]+$\"))) {\n        throw new IllegalArgumentException(\"Invalid input image format\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return videoModel.call(videoPrompt);\n} catch (RuntimeException e) {\n    log.error(\"Video submission failed\", e.getCause());\n    throw new RuntimeException(\n        \"Failed to submit Veo video job — check model name, input image, \"\n        + \"and content policy. Cause: \" + e.getCause().getMessage(), e);\n}","preventionTips":["Verify the model name is a valid Veo model available in your API tier and region.","For image-to-video: test the input image separately — verify it's valid PNG/JPEG before passing.","Use data: URI base64 for input images to avoid network download failures.","Check the Veo API quota and content policy for your prompt.","Log the cause exception to distinguish authentication errors from content-policy rejections."],"tags":["gemini","video","veo","api-error","async"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}