can1357/oh-my-pi · error

Gemini Files API delete failed with HTTP ${response.status}

Error message

Gemini Files API delete failed with HTTP ${response.status}

What it means

Thrown by the Gemini provider's delete() when the DELETE request completed but Gemini returned a non-2xx HTTP status. The status code is embedded in the message so developers can tell authorization problems (401/403) from missing files (404) or rate limits (429).

Source

Thrown at packages/coding-agent/src/blob-broker/provider-files-gemini.ts:169

			};
		},
		async delete(handle: ProviderFileHandle): Promise<void> {
			if (handle.provider !== "google")
				throw new Error("Gemini Files API cannot delete a handle from another provider");
			const name = handle.id;
			if (typeof name !== "string" || !/^files\/[^/]+$/.test(name)) {
				throw new Error("Gemini Files API delete requires a valid file name");
			}
			let response: Response;
			try {
				response = await fetchImpl(`${GEMINI_FILES_RESOURCE_URL}/${name}`, {
					method: "DELETE",
					headers: { "x-goog-api-key": credential },
				});
			} catch {
				throw new Error("Gemini Files API delete request failed");
			}
			if (!response.ok) throw new Error(`Gemini Files API delete failed with HTTP ${response.status}`);
		},
	};
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Treat HTTP 404 as success for cleanup purposes — the file is already gone; do not retry.
  2. For 401/403, re-check the Gemini API key and its Files API permissions.
  3. For 429, add backoff/throttling to bulk deletes to respect per-minute quotas.
  4. Retry 5xx with exponential backoff; deletes are idempotent so retries are safe.
  5. Wrap cleanup loops to continue on individual delete failures instead of aborting the whole batch.

Example fix

// before: failing cleanup on already-deleted file
await geminiClient.delete(handle);
// after
try {
  await geminiClient.delete(handle);
} catch (err) {
  if (!/HTTP 404/.test(err.message)) throw err; // already deleted: fine
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await geminiClient.delete(handle);
} catch (err) {
  const status = Number(/HTTP (\d{3})/.exec(err.message ?? "")?.[1] ?? 0);
  if (status === 404) return; // already deleted
  if (status === 429 || status >= 500) await retryWithBackoff();
  else throw err; // 401/403: credential problem
}

Prevention

When it happens

Trigger: Calling delete() and receiving e.g. 401/403 (bad API key), 404 (file already deleted or never existed), 429 (quota exceeded), or 5xx from the Gemini Files API delete endpoint.

Common situations: Deleting a file that was already removed (404 — often from a concurrent cleanup or double-delete); revoked/expired API key; per-minute quota exhaustion when bulk-deleting many files; Gemini incident causing 5xx.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/fd09d7333d67bcb9. Report an issue: GitHub.