chinabugotech/hutool · error · AIException
Video URI is empty
Error message
Video URI is empty
What it means
A precondition violation thrown by GeminiServiceImpl.downLoadVideo(videoUri, filePath) when videoUri is null, empty, or whitespace-only (StrUtil.isBlank). It is a guard before attempting the HTTP download, so no network call is made. Indicates the caller did not obtain a valid video resource URI from a completed generate-video operation.
Source
Thrown at hutool-ai/src/main/java/cn/hutool/ai/model/gemini/GeminiServiceImpl.java:136
@Override
public String predictVideo(String prompt) {
final Map<String, Object> paramMap = buildPredictVideoRequestMap(prompt);
final HttpResponse response = sendPost(getPredictVideoEndpoint(), JSONUtil.toJsonStr(paramMap));
return response.body();
}
@Override
public String getVideoOperation(String operationName) {
String endPoint = "/" + operationName;
final HttpResponse response = sendGet(endPoint);
return response.body();
}
@Override
public void downLoadVideo(String videoUri, String filePath) {
if (StrUtil.isBlank(videoUri)) {
throw new AIException("Video URI is empty");
}
final HttpResponse response = HttpRequest.get(videoUri)
.header("x-goog-api-key", config.getApiKey())
.setFollowRedirects(true)
.executeAsync();
if (response.isOk()) {
response.writeBody(FileUtil.file(filePath));
} else {
throw new AIException("Download failed with status: " + response.getStatus());
}
}
@Override
public String textToSpeech(String prompt) {
final Map<String, Object> paramMap = buildTextToSpeechRequestMap(prompt);
final HttpResponse response = sendPost(getEndpoint(false), JSONUtil.toJsonStr(paramMap));
return response.body();
}View on GitHub (pinned to 8870454b2a)
Solutions
- Poll getVideoOperation(operationName) until the operation JSON shows done == true.
- Extract the URI from response.generateVideoResponse.samples[].uri (or the signed URL field your Gemini version returns).
- Validate the extracted URI with StrUtil.isNotBlank before calling downLoadVideo.
- Do not pass the operation name or the prompt as the videoUri.
Example fix
// before
String op = gemini.predictVideo("a cat");
gemini.downLoadVideo(null, "/tmp/out.mp4"); // -> Video URI is empty
// after
String opJson = gemini.predictVideo("a cat");
String opName = JSONUtil.parseObj(opJson).getStr("name");
String opResult;
do {
opResult = gemini.getVideoOperation(opName);
} while (!JSONUtil.parseObj(opResult).getBool("done", false));
String uri = JSONUtil.parseObj(opResult)
.getByPath("response.generateVideoResponse.samples[0].uri", String.class);
gemini.downLoadVideo(uri, "/tmp/out.mp4"); Defensive patterns
Strategy: validation
Validate before calling
// Ensure a non-blank URI from a completed operation before download
if (StrUtil.isBlank(videoUri)) {
throw new IllegalStateException("video not ready: operation not done or uri missing");
}
gemini.downLoadVideo(videoUri, filePath); Type guard
// Narrow a parsed operation result to a downloadable URI
static String extractVideoUri(String operationJson) {
JSONObject op = JSONUtil.parseObj(operationJson);
if (!op.getBool("done", false)) return null;
return op.getByPath("response.generateVideoResponse.samples[0].uri", String.class);
} Try / catch
try {
gemini.downLoadVideo(uri, path);
} catch (AIException e) {
if ("Video URI is empty".equals(e.getMessage())) {
// re-poll the operation until done, then re-extract uri
}
throw e;
} Prevention
- Always poll getVideoOperation until done == true before downloading.
- Extract the URI from the documented JSON path.
- Validate with StrUtil.isNotBlank before calling downLoadVideo.
When it happens
Trigger: Calling downLoadVideo before the asynchronous video generation operation has produced a result URI; passing the operation name instead of the video URI; parsing the operation JSON incorrectly and extracting null for the videoUri field.
Common situations: Gemini video generation is asynchronous: predictVideo returns an operation name, getVideoOperation polls it, and only a done operation contains response.generateVideoResponse.samples.uri. Calling downLoadVideo with a blank value means the workflow skipped polling or parsed the wrong field.
Related errors
- File not found!
- Download failed with status:
- Paths or ins is empty !
- Paths length is not equals to ins length !
- Upload failed
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/c6912030828993d1.
Report an issue: GitHub.