{"record":{"id":"af9a62ee77777b40","repo":"conductor-oss/conductor","slug":"openai-video-thumbnail-download-returned-empty-bod","errorCode":null,"errorMessage":"OpenAI Video thumbnail download returned empty body","messagePattern":"OpenAI Video thumbnail download returned empty body","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/providers/openai/api/OpenAIVideoApi.java","lineNumber":232,"sourceCode":"     * @return byte array of the thumbnail image (webp format)\n     */\n    public byte[] downloadThumbnail(String videoId) throws IOException {\n        Request request =\n                new Request.Builder()\n                        .url(baseUrl + \"/v1/videos/\" + videoId + \"/content?variant=thumbnail\")\n                        .header(\"Authorization\", \"Bearer \" + apiKey)\n                        .get()\n                        .build();\n\n        try (Response response = httpClient.newCall(request).execute()) {\n            if (!response.isSuccessful()) {\n                throw new IOException(\n                        \"OpenAI Video thumbnail download failed with status %d\"\n                                .formatted(response.code()));\n            }\n            ResponseBody body = response.body();\n            if (body == null) {\n                throw new IOException(\"OpenAI Video thumbnail download returned empty body\");\n            }\n            return body.bytes();\n        }\n    }\n\n    // -- Helpers --\n\n    /** Safely read the response body as a string, returning empty string if body is null. */\n    private String readResponseBody(Response response) throws IOException {\n        ResponseBody body = response.body();\n        return body != null ? body.string() : \"\";\n    }\n\n    /** Map a MIME type to a file extension for the multipart upload filename. */\n    private String extensionForMimeType(String mimeType) {\n        return switch (mimeType) {\n            case \"image/png\" -> \"png\";\n            case \"image/webp\" -> \"webp\";","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/providers/openai/api/OpenAIVideoApi.java#L214-L250","documentation":"Thrown by OpenAIVideoApi.downloadThumbnail when the thumbnail endpoint returns 2xx but response.body() is null. Defensive guard analogous to 225/227 but for the webp thumbnail binary.","triggerScenarios":"A proxy/gateway returns 200 with no body for the thumbnail endpoint, or an OkHttp interceptor consumes the body first.","commonSituations":"Misconfigured proxy stripping binary responses, shared httpClient logging interceptors draining bodies.","solutions":["Call OpenAI directly to confirm the thumbnail body is present.","Audit OkHttp interceptors for premature body consumption.","Ensure the gateway passes binary content through unchanged."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    byte[] thumb = videoApi.downloadThumbnail(videoId);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"empty body\")) {\n        // proxy stripped body; treat thumbnail as unavailable\n    } else {\n        throw e;\n    }\n}","preventionTips":["Avoid interceptors that consume response bodies.","Verify proxies forward binary content unchanged.","Treat an empty thumbnail body as missing rather than retrying indefinitely."],"tags":["openai","video","sora","thumbnail","empty-body","proxy"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}