chinabugotech/hutool · error · AIException

File not found!

Error message

File not found!

What it means

A precondition violation thrown by GeminiServiceImpl.uploadFile(File) when the file argument is null or file.exists() is false. No network call is made; the guard fails before any upload logic. It means the caller passed a non-existent path.

Source

Thrown at hutool-ai/src/main/java/cn/hutool/ai/model/gemini/GeminiServiceImpl.java:166

	@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();
	}

	@Override
	public String textToSpeech(String prompt, String voice) {
		final Map<String, Object> voiceConfig = MapUtil.of("prebuilt_voice_config", MapUtil.of("voice_name", voice));
		config.putAdditionalConfigByKey("speech_config", MapUtil.of("voice_config", voiceConfig));
		return this.textToSpeech(prompt);
	}

	@Override
	public String uploadFile(final File file) {
		if (null == file || !file.exists()) {
			throw new AIException("File not found!");
		}
		try {
			//自动获取MIME
			String mimeType = FileUtil.getMimeType(file.getName());
			if (StrUtil.isBlank(mimeType)) {
				mimeType = "application/octet-stream";
			}

			String uploadUrl = getUploadBaseUrl();

			//获取 Upload URL
			String metadata = JSONUtil.toJsonStr(MapUtil.of("file", MapUtil.of("display_name", file.getName())));
			final HttpResponse res = HttpRequest.post(uploadUrl)
				.header("x-goog-api-key", config.getApiKey())
				.header("X-Goog-Upload-Protocol", "resumable")
				.header("X-Goog-Upload-Command", "start")
				.header("X-Goog-Upload-Header-Content-Length", String.valueOf(file.length()))
				.header("X-Goog-Upload-Header-Content-Type", mimeType)

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Validate file != null && file.exists() (and isReadable) before calling uploadFile.
  2. Use absolute paths and confirm they exist at call time.
  3. For web uploads, ensure the temp file is materialized on disk first.

Example fix

// before
gemini.uploadFile(new File("/missing/dir/audio.mp3"));
// -> File not found!

// after
File f = new File(path);
if (f == null || !f.exists() || !f.canRead()) {
    throw new IllegalArgumentException("audio file missing: " + path);
}
gemini.uploadFile(f);
Defensive patterns

Strategy: validation

Validate before calling

// Existence + readability pre-check
if (file == null || !file.exists() || !file.canRead()) {
    throw new IllegalArgumentException("file missing or unreadable: " + file);
}
gemini.uploadFile(file);

Type guard

static boolean isUploadable(File f) {
    return f != null && f.exists() && f.canRead();
}

Try / catch

try {
    gemini.uploadFile(file);
} catch (AIException e) {
    if ("File not found!".equals(e.getMessage())) {
        // path wrong / deleted -> resolve absolute path and retry
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing null for the file argument; passing a File whose path does not exist on disk; passing a relative path resolved against an unexpected working directory; the file was deleted between selection and upload.

Common situations: Web upload temp file already cleaned up; wrong absolute path; MultipartFile.transferTo not yet completed before calling uploadFile; typos in the path string.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/4e74818fe565a044. Report an issue: GitHub.