## Summary
When submitting a video-to-video (edit/extend) request to the Interactions API in `background=true` + `store=true` mode with a source video referenced via a valid Files API URI (`https://generativelanguage.googleapis.com/v1beta/files/{id}\`), the POST succeeds and returns an `interaction_id`. However, every subsequent `GET /v1beta/interactions/{id}` returns HTTP 400 with:
```json
{
“error”: {
"message": "Unsupported file uri: blobstore:///genai-api/blobref/global::000050ecbb30026d:000002fa:2:000050ecbb30026d:0000000000000001...",
"code": "invalid_request"
}
}
```
The interaction can never be retrieved, so the generated video is permanently inaccessible to the client, despite the POST having succeeded.
## Environment
| Item | Value |
|—|—|
| Endpoint | `https://generativelanguage.googleapis.com/v1beta/interactions\` |
| API version | `v1beta` |
| Model | `gemini-omni-1.1-flash` |
| API key format | New-format key (`AQ.` prefix), passed via `x-goog-api-key` header |
| Task | Video-to-video (edit / extend) with source video uploaded via Files API |
| Mode | `background: true`, `store: true`, `stream: false`, `response_format.delivery: “uri”` |
| First observed | 2026-10-12 |
| Reproducibility | **100%** — every video-to-video request via Files API URI fails on GET |
## Reproduction Steps
### Step 1: Upload source video via Files API (resumable upload)
```
POST https://generativelanguage.googleapis.com/upload/v1beta/files
Headers:
x-goog-api-key: <API_KEY>
X-Goog-Upload-Protocol: resumable
X-Goog-Upload-Command: start
X-Goog-Upload-Header-Content-Length: 2072651
X-Goog-Upload-Header-Content-Type: video/mp4
Body: {“file”: {“display_name”: “video-source”}}
```
Then finalize the upload. Response:
```json
{
“file”: {
"name": "files/6kqzpdr3kct6",
"uri": "https://generativelanguage.googleapis.com/v1beta/files/6kqzpdr3kct6",
"state": "ACTIVE",
"mimeType": "video/mp4",
"sizeBytes": "2072651"
}
}
```
Polling `GET /v1beta/files/6kqzpdr3kct6` returns `state: “ACTIVE”`.
### Step 2: Submit interaction with the Files API URI
```
POST https://generativelanguage.googleapis.com/v1beta/interactions
Headers:
x-goog-api-key: <API_KEY>
Content-Type: application/json
Body:
{
“model”: “gemini-omni-1.1-flash”,
“stream”: false,
“background”: true,
“store”: true,
“response_format”: {
"type": "video",
"delivery": "uri"
},
“input”: [
{
"type": "video",
"uri": "https://generativelanguage.googleapis.com/v1beta/files/6kqzpdr3kct6",
"mime_type": "video/mp4"
},
{
"type": "text",
"text": "<edit/extend instruction>"
}
]
}
```
**Response: HTTP 200** with:
```json
{
“id”: “v1_ChdiY0hNYXRxeUotMk1fUFVQcHYzS2lRMBIXYmNITWF0cXlKLTJNX1BVUHB2M0tpUTA”,
“status”: “in_progress”
}
```
### Step 3: Poll for the result
```
Headers:
x-goog-api-key: <SAME_API_KEY_AS_STEP_2>
```
**Actual response: HTTP 400**
```json
{
“error”: {
"message": "Unsupported file uri: blobstore:///genai-api/blobref/global::000050ecbb30026d:000002fa:2:000050ecbb30026d:0000000000000001...",
"code": "invalid_request"
}
}
```
**Expected response**: HTTP 200 with the interaction state (`in_progress` / `completed`) and, on completion, the generated video URI in `steps[].content[].uri`.
## Evidence from Production Logs
Full request/response trace from our production system (single request, recordId=3709):
```
19:15:45 Files API upload session started, source video downloaded (2,072,651 bytes)
19:15:47 Files API upload finalized:
uri: https://generativelanguage.googleapis.com/v1beta/files/6kqzpdr3kct6
name: files/6kqzpdr3kct6
19:15:57 File state polling: ACTIVE
19:15:57 POST /v1beta/interactions submitted with input[0] = {
"type": "video",
"uri": "https://generativelanguage.googleapis.com/v1beta/files/6kqzpdr3kct6",
"mime_type": "video/mp4"
}
19:15:57 POST response 200: interactionId=v1_Chdi…, status=in_progress
19:15:58 GET /v1beta/interactions/v1_Chdi… with the SAME API key (keyId=2)
19:15:59 GET response 400: "Unsupported file uri: blobstore:///genai-api/blobref/global::
000050ecbb30026d:000002fa:2:000050ecbb30026d:0000000000000001..."
```
## Key Observations
### 1. Same API key used for POST and GET — this is NOT a cross-key permission issue
Both the Files API upload, the POST `/interactions`, and the GET `/interactions/{id}` use the exact same API key (identified internally as `keyId=2`, apiKey prefix `AQ.Ab8***yTtA`). The bug is not related to key rotation or cross-tenant access.
### 2. The blobstore URI is IDENTICAL across all failing interactions
Every failing GET (15+ different interactions, submitted over 4+ hours, with different source videos uploaded to different `files/{id}` endpoints) returns the **exact same blobstore URI**:
```
blobstore:///genai-api/blobref/global::000050ecbb30026d:000002fa:2:000050ecbb30026d:0000000000000001
```
This strongly suggests a **server-side template/placeholder** that is not being properly resolved per-interaction, rather than a legitimate per-file blob reference. The `:2:` segment in the URI matches our internal `keyId=2`, indicating the server correctly identifies the caller but produces a non-resolvable reference.
### 3. The client submits a valid, publicly-documented Files API URI
Per the [File input methods guide](https://ai.google.dev/gemini-api/docs/file-input-methods) and the [Omni Flash video editing docs](https://ai.google.dev/gemini-api/docs/omni), passing `https://generativelanguage.googleapis.com/v1beta/files/{id}\` as `input[].uri` is the officially recommended way to reference large videos (Base64 inlining is discouraged for videos due to the 33% size inflation and 20 MB request limit).
### 4. Varying `input[].type` does NOT help
We tested both:
| `type` value | Result |
|—|—|
| `“video”` + `uri` | 400 blobstore error |
| `“document”` + `uri` (matching the Python SDK example in the Omni docs) | **Same** 400 blobstore error, same blobstore URI |
The failure is triggered by the **URI reference itself**, not by the `type` discriminator.
### 5. POST succeeds; only GET fails
The interaction is created and (based on the response) enters `in_progress`. It is unclear whether the video is actually generated server-side, because the GET endpoint cannot serialize the stored state back to the client. This means:
- Billing may still occur for a video the client can never retrieve
- The client has no way to distinguish “still processing” from “permanently broken”
## Hypothesized Root Cause
When `background=true` + `store=true` is set, the Interactions service persists the interaction to an internal archive. During persistence, the valid external Files API URI (`https://generativelanguage.googleapis.com/v1beta/files/{id}\`) appears to be rewritten into an internal `blobstore:///genai-api/blobref/global::…` reference. When the GET endpoint later reads the archived interaction and tries to serialize it back to a client-consumable response, the serializer / validator rejects its own internal blobstore format with `“Unsupported file uri”`.
The fact that the blobstore URI is byte-identical across unrelated interactions supports this being a **template-resolution defect on the archival read path**, not a per-file corruption.
## Impact
- **All video-to-video (edit / extend) requests** submitted via `gemini-omni-1.1-flash` with Files API URI input are permanently broken at the retrieval step.
- Video generation via inline Base64 (`type: “video”` + `data: `, as in the REST curl example) still works, but this is impractical for realistic video sizes (>15 MB pre-Base64 hits the 20 MB request limit after 33% inflation).
- Text-to-video and image-to-video paths are unaffected (no Files URI in input).
## Requested Fix
Please investigate the Interactions archival read path so that GET `/v1beta/interactions/{id}` can correctly serialize interactions whose `input[]` contains a Files API URI reference. Either:
1. Resolve the internal `blobstore://` reference back to the original external `https://…/files/{id}` URI before returning the response, or
2. Skip serialization of `input[]` blob references when returning interaction state (the client already knows what it submitted), or
3. Return the resolved video output in `steps[].content[].uri` without echoing the input blob references.
## Workarounds Attempted
| Workaround | Result |
|—|—|
| Use the same API key for upload + POST + GET | ✗ Still 400 |
| Change `input[].type` from `“video”` to `“document”` | ✗ Still 400, same blobstore URI |
| Wait longer before polling (in case it’s a propagation delay) | ✗ Still 400 after 10+ minutes |
| Poll from a different network / IP | ✗ Still 400 |
The only currently working path is inline Base64 (`type: “video”` + `data: `), which is not viable for production video sizes.
## Additional Context
- Our integration follows the official docs precisely (Files API resumable upload → wait for `ACTIVE` → reference by `uri` in `input[]`).
- We have production traffic on this endpoint; the bug affects 100% of video-to-video requests since at least 2026-10-12.
- We are happy to provide additional logs, HAR files, or reproduce on demand with a specific interaction ID if helpful.
## Reference Interaction IDs (for Google backend log lookup)
Failing interactions observed in production (all returning identical blobstore URI):
| recordId | interactionId |
|—|—|
| 3709 | `v1_ChdiY0hNYXRxeUotMk1fUFVQcHYzS2lRMBIXYmNITWF0cXlKLTJNX1BVUHB2M0tpUTA` |
| 3716 | `v1_Chd4SlBOYXVEZkE4RFJ6N0lQcmZIMHlRMBIXeEpQTmF1RGZBOERSejdJUHJmSDB5UTA` |
| 3704 | `v1_ChdJN1BNYXVPMUJyN2lfdU1QeU96VTBBbxIXSTdQTWF1TzFCcjdpX3VNUHlPelUwQW8` |
| 3703 | `v1_ChYtYkxNYXA2bk1OU2cxTWtQZ08zQ0dBEhYtYkxNYXA2bk1OU2cxTWtQZ08zQ0dB` |
| 3695 | `v1_ChdQYXZNYXBlVUo3ZmNfdU1QaVBQM3dBRRIXUGF2TWFwZVVKN2ZjX3VNUGlQUDN3QUU` |
| 3694 | `v1_Chd2S3JNYW8zd0c2RDYtOFlQejZmc3NRbxIXdktyTWFvM3dHNkQ2LThZUHo2ZnNzUW8` |
| 3693 | `v1_ChdFYXJNYXJYU0xOSFZqckVQdElHVjhBURIXRWFyTWFyWFNMTkhWanJFUHRJR1Y4QVE` |
| 3691 | `v1_ChdwS25NYXJQUU9fellqTWNQb3J5YW9BVRIXcEtuTWFyUFFPX3pZak1jUG9yeWFvQVU` |
| 3690 | `v1_ChdFYW5NYXUySE1LQ21fdU1Qc082SGdBNBIXRWFuTWF1MkhNS0NtX3VNUHNPNkhnQTQ` |
| 3689 | `v1_Chc0S2pNYXA2WUx1NjJzT0lQNnZPU3FBTRIXNEtqTWFwNllMdTYyc09JUDZ2T1NxQU0` |
| 3679 | `v1_ChZZNXJNYXE3ZUdiZVAxTWtQemVLM0tBEhZZNXJNYXE3ZUdiZVAxTWtQemVLM0tB` |
| 3673 | `v1_ChdWSm5NYXNtaU1jNncxTWtQc3JQbTZRSRIXVkpuTWFzbWlNYzZ3MU1rUHNyUG02UUk` |
| 3672 | `v1_ChdvWmpNYXV5QlBOU1UzOUlQNElmY2lRWRIXb1pqTWF1eUJQTlNVMzlJUDRJZmNpUVk` |