can1357/oh-my-pi · error

Gemini Files API cannot delete a handle from another provide

Error message

Gemini Files API cannot delete a handle from another provider

What it means

Thrown by the Gemini provider's delete() when the supplied ProviderFileHandle was issued by a different provider (handle.provider !== "google"). Provider file handles are provider-scoped: a handle holding an OpenAI file id cannot be deleted through the Gemini Files API, so the library fails fast with a clear message instead of making a doomed request.

Source

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

			const file = parseFinalizedFile(await responseJson(finalizeResponse, "finalize"));
			return {
				provider: "google",
				id: file.name,
				uri: file.uri,
				mimeType: file.mimeType,
				bytes: byteLength,
				expiresAt: file.expiresAt,
				delete: {
					method: "DELETE",
					url: `${GEMINI_FILES_RESOURCE_URL}/${file.name}`,
					headers: { "x-goog-api-key": credential },
				},
			};
		},
		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. Route each handle to the client whose provider matches handle.provider before calling delete().
  2. Store the provider alongside the handle id in your persistence layer and look up the correct client by that field.
  3. If migrating between providers, re-upload the file to the new provider and use the newly returned handle.
  4. Add a guard/dispatch map in caller code: { google: geminiClient, openai: openaiClient }[handle.provider].delete(handle).

Example fix

// before
geminiClient.delete(handle); // handle.provider === "openai"
// after
if (handle.provider === "google") {
  await geminiClient.delete(handle);
} else {
  await openaiClient.delete(handle);
}
Defensive patterns

Strategy: type-guard

Type guard

function isGoogleHandle(h: ProviderFileHandle): h is ProviderFileHandle & { provider: "google" } {
  return h.provider === "google";
}
// call site: if (!isGoogleHandle(handle)) routeToOtherProvider(handle);

Prevention

When it happens

Trigger: Calling delete() on the Gemini file client with a handle whose provider field is e.g. "openai" — typically because the handle was returned by a different provider's upload or stored in shared state (session, DB) and passed to the wrong client.

Common situations: Mixing multiple blob-broker providers (OpenAI and Gemini) in one session and routing cleanup through a single client; persisting handles without the provider field and reconstructing them with the wrong client; switching model providers mid-session while retaining old file handles.

Related errors


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