# ¿Nano Banana Pro dice 'Unsupported file URI type'? Corrige primero la ruta de archivo de Gemini

> Si Nano Banana Pro rechaza el URI de una imagen, revisa el valor que realmente envía tu aplicación. En generateContent puedes usar una URL HTTPS admitida, bytes en inlineData o el URI de Files API; el éxito se confirma con la imagen editada en la respuesta.

- URL: https://blog.laozhang.ai/es/posts/nano-banana-pro-unsupported-file-uri-type
- Published: 2026-04-09
- Updated: 2026-10-06
- Author: LaoZhang AI Team (https://blog.laozhang.ai/es/about)
- Topic: Resolución de problemas
- Tags: Nano Banana Pro, Gemini API, Files API, image_url, subida de archivos

---
Si Nano Banana Pro responde con `Unsupported file URI type` o `Invalid or unsupported file uri`, **revisa primero la referencia de imagen que sale de tu aplicación**. Comprueba el endpoint, el modelo y el valor serializado: una expresión como `{{ $json.imageUrls }}`, una lista, una ruta local y una URL HTTPS son entradas distintas.

En la API nativa de Gemini, una URL HTTPS pública o firmada **sí puede usarse como entrada** cuando cumple las condiciones de recuperación y del modelo. La [guía oficial de entrada de archivos, actualizada el 1 de octubre de 2026](https://ai.google.dev/gemini-api/docs/generate-content/file-input-methods), documenta esta opción. Por tanto, no necesitas subir obligatoriamente toda imagen remota a Files API. Si la recuperación de la URL falla, puedes enviar los bytes en `inlineData` y mantener tanto `generateContent` como Nano Banana Pro, cuyo identificador actual es [`gemini-3-pro-image`](https://ai.google.dev/gemini-api/docs/generate-content/image-generation).

El objetivo de la corrección es recibir la imagen editada que pediste. Una respuesta HTTP 200 o una descripción de la foto no demuestran que la edición haya funcionado.

## Identifica qué referencia está fallando

Antes de cambiar el código, mira el cuerpo JSON final de la petición, después de evaluar las expresiones de tu automatización. Oculta la clave de API, los parámetros de las URL firmadas y el contenido privado de las imágenes al preparar un registro para soporte.

| Valor enviado | Qué comprobar | Corrección que conserva la tarea de edición |
| --- | --- | --- |
| `{{ $json.imageUrls }}` o un nombre de variable | Si salió como texto literal, la expresión no se evaluó | Resuelve el campo antes de construir el JSON y comprueba su valor final |
| Una lista de URL | `fileUri` debe ser una cadena, no un array ni un array convertido en texto | Crea una parte de imagen por cada URL |
| `https://…` | Acceso para Gemini, caducidad, MIME, modelo y condiciones de recuperación | Usa una URL admitida o envía los bytes mediante `inlineData` |
| `data:image/png;base64,…` | Si lo pusiste en `fileUri` nativo | Pasa el base64 sin el prefijo a `inlineData.data` |
| `/tmp/foto.png` o `file:///…` | La ruta pertenece a tu dispositivo | Lee los bytes o sube el archivo; no envíes la ruta como URI remoto |
| `files/abc123` | Si copiaste `name` en lugar de `uri` | Usa exactamente el `uri` devuelto por Files API |
| `gs://bucket/foto.png` | Si estás en Gemini Developer API o en Vertex AI | En Gemini, sigue el registro de GCS; en Vertex, su contrato propio |

No todos estos fallos producen exactamente el mismo mensaje. La [referencia de `generateContent`](https://ai.google.dev/api/generate-content) define `fileUri` como una cadena y `inlineData.data` como bytes codificados en base64. Esa distinción sirve para corregir la entrada; el texto concreto del error ayuda a localizar quién la rechazó.

En REST nativo, la petición se envía a:

```text
POST https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image:generateContent
```

Los ejemplos siguientes usan los campos JSON `contents`, `parts`, `fileData` e `inlineData`. Algunas muestras REST utilizan nombres con guion bajo y los SDK tienen sus propias convenciones. Sigue una forma documentada para tu cliente; no mezcles dentro de `parts` el campo `image_url` de Chat Completions.

## Usar una URL HTTPS en generateContent

Para una imagen disponible en una URL admitida, guarda este cuerpo como `request-url.json`. Sustituye la dirección de ejemplo por la tuya y el MIME por el del archivo real:

```json
{
  "contents": [{
    "role": "user",
    "parts": [
      {"text": "Cambia el fondo a azul claro. Conserva el objeto principal."},
      {"fileData": {
        "mimeType": "image/png",
        "fileUri": "https://example.com/referencia.png"
      }}
    ]
  }],
  "generationConfig": {
    "responseModalities": ["TEXT", "IMAGE"]
  }
}
```

La dirección es un marcador, no una imagen de prueba. Para varias imágenes, añade varias partes `fileData`; no pongas todas las direcciones en un único `fileUri`. El texto de la instrucción ocupa otra parte, porque cada parte representa un tipo de contenido.

Según la [guía de métodos de entrada](https://ai.google.dev/gemini-api/docs/generate-content/file-input-methods), Gemini recupera las URL durante el procesamiento. Esto incluye HTTPS públicos y determinadas URL firmadas, como las de S3 o Azure. La familia Gemini 2.0 no admite este método; una respuesta antigua sobre Gemini 2.0 no define el comportamiento de Pro actual.

Si falla una URL, comprueba lo siguiente:

1. La dirección lleva al archivo de imagen, no a una página de inicio de sesión, una vista previa HTML o una pantalla de descarga.
2. Sigue siendo válida durante la petición y concede el acceso necesario. Que se abra en tu navegador, con tu sesión iniciada, no demuestra que Gemini pueda recuperarla.
3. El MIME corresponde al archivo y el tamaño cumple los límites del método, del modelo y de cualquier pasarela intermedia.
4. El servicio permite recuperar esa URL. Un estado `URL_RETRIEVAL_STATUS_UNSAFE` indica un rechazo de recuperación por seguridad; no es una instrucción para eludirlo.

Para una imagen privada, conserva sus controles de acceso. Puedes usar una URL firmada con los permisos y la duración adecuados o enviar los bytes desde tu aplicación. No hace falta convertir un bucket privado en público para probar la alternativa inline.

## Enviar una imagen local con inlineData y obtener la edición

Esta opción evita que el servidor tenga que descargar la imagen desde una URL. La [guía oficial de generación de imágenes](https://ai.google.dev/gemini-api/docs/generate-content/image-generation) documenta la edición a partir de una imagen y la devolución de partes de imagen en la respuesta.

El siguiente recorrido crea el JSON, lo envía al modelo Pro y guarda las imágenes devueltas. Necesitas una imagen pequeña que puedas usar, Python 3, `curl` y una clave válida de Gemini disponible como `GEMINI_API_KEY`. La llamada a la API usa tu cuenta y puede generar cargos. Aquí se ha comprobado la construcción del JSON y la extracción de una respuesta sintética, sin realizar una llamada al modelo.

### 1. Construye el JSON desde los bytes del archivo

Guarda este script como `crear_peticion.py` y ejecútalo con `python3 crear_peticion.py foto.png`. Admite extensiones PNG, JPEG y WebP; el archivo debe tener realmente el formato indicado por su extensión.

```python
import base64
import json
import sys
from pathlib import Path

imagen = Path(sys.argv[1])
mimes = {
    ".png": "image/png",
    ".jpg": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".webp": "image/webp",
}
mime = mimes.get(imagen.suffix.lower())
if mime is None:
    raise SystemExit("Usa una imagen PNG, JPEG o WebP.")
contenido = imagen.read_bytes()
if not contenido:
    raise SystemExit("El archivo está vacío.")

peticion = {
    "contents": [{
        "role": "user",
        "parts": [
            {"text": "Cambia el fondo a azul claro. Conserva el objeto principal."},
            {"inlineData": {
                "mimeType": mime,
                "data": base64.b64encode(contenido).decode("ascii"),
            }},
        ],
    }],
    "generationConfig": {"responseModalities": ["TEXT", "IMAGE"]},
}
Path("request-inline.json").write_text(
    json.dumps(peticion, ensure_ascii=False), encoding="utf-8"
)
```

`inlineData.data` contiene solo el base64 de los bytes. **No añadas `data:image/png;base64,`**: ese prefijo pertenece a una URL de datos, no al campo de bytes nativo. Cambiar el prefijo de una cadena incorrecta tampoco sustituye a leer el archivo original.

### 2. Envía la petición al mismo modelo

```bash
curl --fail-with-body \
  "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image:generateContent" \
  -H "x-goog-api-key: ${GEMINI_API_KEY}" \
  -H "Content-Type: application/json" \
  --data-binary @request-inline.json \
  -o response.json
```

Para probar el ejemplo de URL anterior, cambia únicamente `@request-inline.json` por `@request-url.json`. Conserva el endpoint, el modelo y la instrucción; así puedes comparar las dos formas de entrada sin convertir la prueba en otra tarea.

Si recibes un error de acceso al modelo, comprueba su disponibilidad para tu cuenta. No sustituyas Pro por un modelo que solo describe imágenes para dar por resuelto un fallo de edición.

### 3. Guarda las partes de imagen de la respuesta

Guarda este script como `guardar_imagenes.py` y ejecuta `python3 guardar_imagenes.py` desde el directorio de `response.json`:

```python
import base64
import json
from pathlib import Path

respuesta = json.loads(Path("response.json").read_text(encoding="utf-8"))
extensiones = {
    "image/png": ".png",
    "image/jpeg": ".jpg",
    "image/webp": ".webp",
}
guardadas = 0
for candidato in respuesta.get("candidates", []):
    for parte in candidato.get("content", {}).get("parts", []):
        datos = parte.get("inlineData")
        if not datos or not datos.get("mimeType", "").startswith("image/"):
            continue
        extension = extensiones.get(datos["mimeType"])
        if extension is None:
            raise SystemExit("La respuesta contiene un formato de imagen no previsto.")
        contenido = base64.b64decode(datos["data"], validate=True)
        guardadas += 1
        Path(f"edicion-{guardadas}{extension}").write_bytes(contenido)

if guardadas == 0:
    raise SystemExit("No se recibió una parte de imagen; revisa la respuesta completa.")
print(f"Imágenes guardadas: {guardadas}")
```

Abre la imagen guardada y comprueba el cambio solicitado. Si solo hay texto, revisa el contenido de la respuesta, sus motivos de finalización o bloqueo y la configuración de salida. La ausencia del error de URI demuestra menos que una edición correcta.

## Subir la imagen a Files API: usa uri, no name

Si prefieres reutilizar un archivo subido, [Files API](https://ai.google.dev/api/files) devuelve un recurso con campos distintos: `name` identifica el recurso para consultarlo; `uri` es la referencia que debes pasar como entrada del modelo. No construyas ese URI a partir del ID.

Este ejemplo REST sube un PNG mediante el protocolo reanudable. Requiere `foto.png`, la misma clave de Gemini y un shell con `curl` y Python 3. No se ha ejecutado aquí contra el servicio.

```bash
set -e

bytes=$(python3 -c 'from pathlib import Path; print(Path("foto.png").stat().st_size)')

curl --fail-with-body \
  "https://generativelanguage.googleapis.com/upload/v1beta/files" \
  -H "x-goog-api-key: ${GEMINI_API_KEY}" \
  -H "X-Goog-Upload-Protocol: resumable" \
  -H "X-Goog-Upload-Command: start" \
  -H "X-Goog-Upload-Header-Content-Length: ${bytes}" \
  -H "X-Goog-Upload-Header-Content-Type: image/png" \
  -H "Content-Type: application/json" \
  --data '{"file":{"display_name":"referencia-edicion"}}' \
  -D upload-headers.txt -o upload-start.json

upload_url=$(python3 -c 'from pathlib import Path; h=Path("upload-headers.txt").read_text(); print(next(line.split(":",1)[1].strip() for line in h.splitlines() if line.lower().startswith("x-goog-upload-url:")))')

curl --fail-with-body "${upload_url}" \
  -H "Content-Length: ${bytes}" \
  -H "X-Goog-Upload-Offset: 0" \
  -H "X-Goog-Upload-Command: upload, finalize" \
  --data-binary @foto.png -o upload-result.json
```

Detente si falla cualquiera de los dos pasos: no continúes con una respuesta de error como si fuera un archivo válido. Trata `upload-headers.txt` y la URL de subida como datos sensibles.

Después, este script construye `request-file.json` a partir de la respuesta real:

```python
import json
from pathlib import Path

archivo = json.loads(
    Path("upload-result.json").read_text(encoding="utf-8")
)["file"]
if archivo.get("state") != "ACTIVE":
    raise SystemExit("El archivo no está ACTIVE; consulta su estado antes de generar.")
uri = archivo["uri"]
if not isinstance(uri, str) or not uri:
    raise SystemExit("Files API no devolvió un uri válido.")

peticion = {
    "contents": [{
        "role": "user",
        "parts": [
            {"text": "Cambia el fondo a azul claro. Conserva el objeto principal."},
            {"fileData": {
                "mimeType": archivo["mimeType"],
                "fileUri": uri,
            }},
        ],
    }],
    "generationConfig": {"responseModalities": ["TEXT", "IMAGE"]},
}
Path("request-file.json").write_text(json.dumps(peticion), encoding="utf-8")
```

Envía este JSON con la misma llamada a `generateContent`, cambiando el archivo de entrada a `@request-file.json`, y utiliza el extractor anterior.

Si el estado es `PROCESSING`, consulta `GET https://generativelanguage.googleapis.com/v1beta/{name}` con tus credenciales hasta obtener `ACTIVE`, con una espera y un plazo máximo definidos en tu aplicación. Si es `FAILED`, revisa el error del recurso y detén los reintentos. No envíes un archivo que sigue procesándose ni mantengas un bucle infinito.

Las subidas ordinarias se conservan durante **48 horas**. Si guardaste un URI para usarlo días después, consulta el recurso y su `expirationTime`, cuando exista, y vuelve a subir el archivo si ha caducado. Que la subida termine correctamente no garantiza que cualquier modelo acepte cualquier tipo de archivo.

## Un objeto gs:// necesita el contrato de GCS correspondiente

En Gemini Developer API, el registro de objetos GCS es una alternativa a copiar los bytes mediante una subida. La operación oficial es `POST https://generativelanguage.googleapis.com/v1beta/files:register`, con un cuerpo como este:

```json
{"uris": ["gs://mi-bucket/referencia.png"]}
```

El [registro de Files API](https://ai.google.dev/api/files) devuelve `files[]`. Utiliza el `uri` del archivo devuelto para construir la parte `fileData`, en lugar de asumir que la cadena `gs://` original basta en tu petición. Un fallo en un objeto hace fallar la operación de registro completa.

Este método requiere **autorización OAuth del solicitante y acceso adecuado al objeto**, además de la configuración del servicio. La [guía oficial de entrada de archivos](https://ai.google.dev/gemini-api/docs/generate-content/file-input-methods) especifica el acceso del agente de servicio de Gemini, incluido Storage Object Viewer sobre el bucket correspondiente, y los permisos del solicitante. Una clave de API por sí sola no sustituye esos requisitos; la generación mantiene también sus propias credenciales.

El registro no copia el archivo y permite acceso durante un máximo de 30 días por registro. No le apliques automáticamente las 48 horas de una subida ordinaria. Si no dispones de la identidad o los permisos necesarios, usa una imagen local autorizada mediante inline o una URL admitida; cambiar permisos de almacenamiento requiere una decisión aparte.

Si tu aplicación ya utiliza Vertex AI, comprueba su hostname, proyecto, ubicación e identidad. El contrato de Vertex para `gs://` es distinto del de Gemini Developer API. Cambiar de una API a otra modifica la integración y no debe hacerse como un ajuste oculto para eliminar este error.

## Automatizaciones, modo compatible y pasarelas

![Relación entre las entradas de imagen, los campos del cuerpo de la petición y las rutas de Gemini](https://blog.laozhang.ai/posts/es/nano-banana-pro-unsupported-file-uri-type/img/uri-routes.webp)

En una automatización, comprueba el resultado de la expresión justo antes del envío. Si `imageUrls` es una lista, selecciona una imagen o transforma cada elemento en una parte independiente. Si el campo no existe, detén la ejecución con un mensaje claro. En JavaScript, `JSON.stringify` puede omitir una propiedad cuyo valor sea `undefined`; convertir el valor explícitamente en texto produce un resultado distinto. Mira el JSON enviado, no solo la variable que esperabas tener.

Un [caso publicado por APIYI en abril de 2026](https://help.apiyi.com/en/nano-banana-pro-unsupported-file-uri-type-error-fix-en.html) muestra el literal `{{ $json.imageUrls }}` dentro del error. Es un ejemplo de referencia sin evaluar, no una prueba de que todos los fallos de URI tengan esa causa ni una receta universal para n8n o Make.

En la [compatibilidad OpenAI de Gemini](https://ai.google.dev/gemini-api/docs/openai), la comprensión de imágenes utiliza una forma diferente:

```json
{
  "type": "image_url",
  "image_url": {"url": "data:image/png;base64,BASE64_DE_LA_IMAGEN"}
}
```

Es un fragmento de contenido para la ruta compatible `/v1beta/openai/`, no una petición nativa completa. El marcador debe sustituirse por el base64 real. Que este formato esté documentado para comprender imágenes no demuestra que cualquier llamada a Chat Completions pueda devolver una edición de Pro. Si necesitas la edición nativa mostrada aquí, conserva su modelo, endpoint y partes de salida; no combines los dos cuerpos JSON.

Las pasarelas pueden modificar también el transporte. El [issue 10349 de Vercel, de noviembre de 2025](https://github.com/vercel/ai/issues/10349), describe una diferencia entre pasar una URL por la pasarela y descargarla a bytes desde el SDK. Ese informe histórico no demuestra un fallo actual en todas las versiones. Sí explica una precaución útil: si el SDK funciona, averigua si envió la URL o los bytes antes de concluir que el servidor recuperó la misma dirección.

Anota proveedor, versión del cliente, hostname, modelo y forma del cuerpo final. Si un wrapper impone un límite o convierte campos, sigue su documentación. Por ejemplo, la [ruta de Comfy para Nano Banana Pro](https://docs.comfy.org/ja/development/comfy-router/models/google/nano-banana-pro/code) usa credenciales y un hostname propios; documenta 20 MB para inline y 24 horas para sus URL firmadas de salida. Esas cifras no son la duración ni el límite general de Files API.

## Comprueba el resultado y decide dónde seguir

![Secuencia de comprobación de la referencia, el archivo, su caducidad y el comportamiento del cliente](https://blog.laozhang.ai/posts/es/nano-banana-pro-unsupported-file-uri-type/img/verify-flow.webp)

Haz la prueba con una imagen pequeña y una modificación fácil de reconocer. Conserva la misma instrucción, `gemini-3-pro-image` y `generateContent`; cambia solo la referencia que estás diagnosticando.

- Si la URL falla y los bytes inline generan la edición, has aislado una diferencia de recuperación o transporte. Revisa el acceso de la URL y lo que hace el cliente.
- Si fallan ambas entradas, comprueba el archivo, el MIME, el JSON final y las capacidades del modelo. No sigas modificando la URL cuando la petición ya envía bytes.
- Si se acepta un archivo subido pero deja de funcionar más tarde, consulta su estado y caducidad antes de reutilizar el URI.
- Si hay una parte de imagen, abre el archivo y verifica la edición. Un texto explicativo no cumple ese resultado.

La guía general documenta hasta 100 MB para ciertos métodos inline y URL, 2 GB por archivo subido y 20 GB de almacenamiento por proyecto. Estos son límites del método; pueden existir restricciones adicionales del modelo, del tipo de archivo o de la pasarela. Tampoco implica que Pro acepte audio o vídeo: la documentación actual no admite entrada de audio en Pro y limita vídeo a imagen a otros modelos concretos. Empieza por una imagen válida, en vez de probar una tabla genérica de formatos.

Cuando la referencia ya es correcta, un 403 de acceso, un 404 de modelo, un 429 de cuota o un problema con la firma de pensamiento necesitan su propia comprobación. Conserva el mensaje y la respuesta exactos, sin publicar secretos; no los conviertas automáticamente en otro fallo de URI.

## Preguntas frecuentes

### ¿Puedo poner una URL HTTPS directamente en fileUri?

Sí, en `generateContent` puedes utilizar HTTPS públicos o firmados que cumplan las condiciones de acceso, seguridad y límites de la [guía oficial](https://ai.google.dev/gemini-api/docs/generate-content/file-input-methods). No es obligatorio subir antes toda imagen remota. La familia Gemini 2.0 queda fuera de este método y una pasarela puede tener condiciones distintas.

### ¿Por qué data:image funciona en image_url pero falla en fileUri?

Porque son campos de APIs diferentes. La ruta compatible documenta una URL de datos dentro de `image_url.url`; la API nativa recibe los bytes base64 sin prefijo en `inlineData.data`. Cambia la estructura completa de la parte correspondiente, no solo el nombre del campo.

### ¿Debo subir un archivo local para editarlo con Pro?

Puedes subirlo, pero también puedes leer sus bytes y enviarlos mediante `inlineData`. Una ruta como `/tmp/foto.png` no permite que el servidor lea tu disco. Ambos métodos requieren un formato y un tamaño admitidos para la tarea.

### ¿Todos los URI de archivo caducan a las 48 horas?

No. Las 48 horas corresponden a subidas ordinarias de Files API. El registro GCS puede conceder hasta 30 días por registro; una URL firmada externa tiene su propia caducidad y una pasarela puede definir otra. Comprueba el recurso que estás utilizando, no una duración tomada de otro servicio.

### ¿Basta con que la petición deje de devolver Unsupported file URI type?

No para dar por resuelta una edición. Comprueba que la respuesta contiene una parte de imagen y que el archivo guardado cumple el cambio solicitado. Mantener el mismo Pro y `generateContent` permite verificar el resultado que necesitabas desde el principio.

## Fuentes

Páginas externas que cita esta guía, en el orden en que aparecen. Última actualización: 2026-10-06.

- [guía oficial de entrada de archivos, actualizada el 1 de octubre de 2026](https://ai.google.dev/gemini-api/docs/generate-content/file-input-methods) (ai.google.dev)
- [gemini-3-pro-image](https://ai.google.dev/gemini-api/docs/generate-content/image-generation) (ai.google.dev)
- [referencia de generateContent](https://ai.google.dev/api/generate-content) (ai.google.dev)
- [Files API](https://ai.google.dev/api/files) (ai.google.dev)
- [caso publicado por APIYI en abril de 2026](https://help.apiyi.com/en/nano-banana-pro-unsupported-file-uri-type-error-fix-en.html) (help.apiyi.com)
- [compatibilidad OpenAI de Gemini](https://ai.google.dev/gemini-api/docs/openai) (ai.google.dev)
- [issue 10349 de Vercel, de noviembre de 2025](https://github.com/vercel/ai/issues/10349) (github.com)
- [ruta de Comfy para Nano Banana Pro](https://docs.comfy.org/ja/development/comfy-router/models/google/nano-banana-pro/code) (docs.comfy.org)
