|

Решение 6 распространенных причин и способов исправления ошибки «required oneof field data» в модели изображений Gemini

Примечание автора: Подробное объяснение 6 распространённых причин ошибки 400 required oneof field data must have one initialized field при вызове изображений Gemini, таких как gemini-3.1-flash-image-preview, и соответствующие способы их исправления.

gemini-image-api-required-oneof-field-data-error-fix-ru 图示

При вызове моделей gemini-3.1-flash-image-preview (Nano Banana 2) или gemini-3.0-pro-image (Nano Banana Pro) для генерации изображений многие разработчики сталкиваются с этой запутанной ошибкой 400:

{
  "status_code": 400,
  "error": {
    "message": "* GenerateContentRequest.contents[0].parts[2].data: required oneof field 'data' must have one initialized field",
    "type": "upstream_error",
    "code": 400
  }
}

Основной смысл этой ошибки: в вашем теле запроса поле data какого-то элемента parts пустое или имеет неправильный формат. Ошибка 400 относится к ошибкам параметров клиентского запроса, она не исправится автоматически — нужно обязательно исправить код.

В этой статье мы разберём 6 распространённых причин, вызывающих эту ошибку. К каждой причине прилагается сравнение ошибочного и правильного кода, что поможет вам быстро найти и устранить проблему.

Ключевая ценность: Прочитав эту статью, вы сможете по индексу parts[N] из сообщения об ошибке точно определить место проблемы и последовательно проверить все 6 причин. Обычно на исправление уходит не более 5 минут.


Основной анализ ошибки "required oneof field data" в моделях изображений Gemini

Ключевой момент Объяснение Направление проверки
Суть ошибки В массиве parts присутствуют пустые или некорректно сформированные элементы Проверьте каждый элемент в contents[].parts[]
Ключевая подсказка parts[2] указывает на 3-й элемент (отсчёт с 0) Напрямую перейдите к соответствующему элементу part
Тип ошибки 400 INVALID_ARGUMENT, ошибка на стороне клиента Не исправится автоматически, необходимо изменить код
Область воздействия Общая для всех моделей изображений Gemini Применимо к NB2, NB Pro, Gemini Flash
Сложность исправления Низкая, обычно проблема в формате Достаточно исправить в соответствии с правильным форматом

Расшифровка структуры сообщения об ошибке в моделях изображений Gemini

Давайте разберём структуру сообщения об ошибке — это ключ к локализации проблемы:

GenerateContentRequest.contents[0].parts[2].data
                       ^^^^^^^^     ^^^^^^^^
                       │            │
                       │            └── 3-й part (индексация с 0)
                       └── 1-й блок content
  • contents[0]: Указывает на первый объект content в теле вашего запроса.
  • parts[2]: Указывает на 3-й элемент part внутри этого content.
  • data: Поле данных этого part пустое или не было правильно инициализировано.

Логика проверки: Непосредственно проверьте в вашем коде 3-й элемент ([2]) массива parts, который находится внутри 1-го элемента ([0]) массива contents. Посмотрите, что именно вы в него передаёте.

gemini-image-api-required-oneof-field-data-error-fix-ru 图示


Причина 1: В массиве parts присутствуют пустые объекты или строки

Это самая распространённая причина. В массиве запроса parts содержатся пустые элементы, такие как {}, null, пустая строка "".

Неправильный вариант Правильный вариант
parts содержит пустой объект {} Каждый part должен содержать поле text или inlineData
parts содержит {"text": ""} Пустой текст также вызовет ошибку, напишите хотя бы один символ
parts содержит элемент null Удалите все значения null

Неправильный код:

# ❌ parts содержит пустой объект
payload = {
    "contents": [{
        "parts": [
            {"text": "Generate a cat image"},
            {},                              # ← Пустой объект, вызовет ошибку
            {"text": "in watercolor style"}
        ]
    }]
}

Правильный код:

# ✅ Каждый part содержит валидные данные
payload = {
    "contents": [{
        "parts": [
            {"text": "Generate a cat image in watercolor style"}
        ]
    }]
}

Как исправить: Объедините текст в один text part или убедитесь, что каждый part содержит валидные поля text или inlineData.

Причина 2: Пустые или некорректные данные base64 для изображения

При отправке запроса типа "изображение-в-изображение" данные base64 в поле inlineData могут быть пустыми, повреждёнными или иметь неверный формат.

Неправильный код:

# ❌ Данные base64 содержат префикс data URI
payload = {
    "contents": [{
        "parts": [
            {
                "inlineData": {
                    "mimeType": "image/png",
                    "data": "data:image/png;base64,iVBORw0KGgo..."  # ← Не должен содержать префикс
                }
            },
            {"text": "Change the background to blue"}
        ]
    }]
}
# ❌ Данные base64 — пустая строка
"inlineData": {
    "mimeType": "image/jpeg",
    "data": ""          # ← Пустые данные, сразу вызовут ошибку
}

Правильный код:

import base64
import pathlib

# ✅ Правильное чтение изображения и преобразование в чистый base64
image_bytes = pathlib.Path("input.png").read_bytes()
image_b64 = base64.b64encode(image_bytes).decode("utf-8")

payload = {
    "contents": [{
        "parts": [
            {
                "inlineData": {
                    "mimeType": "image/png",
                    "data": image_b64       # ← Чистая строка base64, без префикса
                }
            },
            {"text": "Change the background to blue"}
        ]
    }]
}

Как исправить:

  • Поле data принимает только чистую строку base64, без префикса data:image/png;base64,
  • Убедитесь, что файл изображения действительно существует и успешно прочитан, чтобы избежать передачи пустой строки
  • mimeType должен соответствовать реальному формату изображения (image/png, image/jpeg, image/webp)

Причина 3: Объект File не был правильно преобразован в ссылку на контент

После загрузки файла через Files API Google GenAI SDK, передача объекта File напрямую в contents может привести к тому, что SDK не сможет его корректно преобразовать.

Неправильный код:

from google import genai

client = genai.Client(api_key="YOUR_KEY")

# Загружаем файл
file = client.files.upload(file="photo.png")

# ❌ В некоторых версиях SDK прямая передача объекта File может завершиться ошибкой
response = client.models.generate_content(
    model="gemini-3.1-flash-image-preview",
    contents=["Edit this image", file]    # ← Объект File может не преобразоваться автоматически
)

Правильный код:

from google import genai
from google.genai import types

client = genai.Client(api_key="YOUR_KEY")

# Загружаем файл
file = client.files.upload(file="photo.png")

# ✅ Способ 1: Вручную создать ссылку на файл
response = client.models.generate_content(
    model="gemini-3.1-flash-image-preview",
    contents=[
        types.Content(parts=[
            types.Part(file_data=types.FileData(file_uri=file.uri, mime_type=file.mime_type)),
            types.Part(text="Edit this image: change background to sunset")
        ])
    ],
    config=types.GenerateContentConfig(
        response_modalities=["TEXT", "IMAGE"]
    )
)
# ✅ Способ 2: Использовать inlineData для прямой передачи base64 (более надёжно)
import base64, pathlib

image_b64 = base64.b64encode(pathlib.Path("photo.png").read_bytes()).decode()

response = client.models.generate_content(
    model="gemini-3.1-flash-image-preview",
    contents=[
        types.Content(parts=[
            types.Part(inline_data=types.Blob(mime_type="image/png", data=image_b64)),
            types.Part(text="Edit this image: change background to sunset")
        ])
    ],
    config=types.GenerateContentConfig(
        response_modalities=["TEXT", "IMAGE"]
    )
)

Как исправить: Рекомендуется использовать способ inlineData + base64 для прямой передачи данных изображения — это стабильнее и надёжнее, чем Files API.

Причина 4: История многораундового диалога содержит пустой контент

При редактировании изображения в многораундовом диалоге, если ответ из предыдущего раунда не был обработан корректно, в историю диалога может попасть пустой блок content.

Неправильный код:

# ❌ В истории диалога присутствуют пустые parts
history = [
    {"role": "user", "parts": [{"text": "Generate a logo"}]},
    {"role": "model", "parts": []},        # ← Пустые parts, вызовут ошибку
    {"role": "user", "parts": [{"text": "Make it blue"}]}
]

payload = {"contents": history}

Правильный код:

# ✅ Отфильтруйте пустые блоки content
history = [
    {"role": "user", "parts": [{"text": "Generate a logo"}]},
    {"role": "model", "parts": [{"text": "Here is the logo I generated."}]},
    {"role": "user", "parts": [{"text": "Make it blue"}]}
]

# Безопасная фильтрация: удаляем записи с пустыми parts
clean_history = [msg for msg in history if msg.get("parts") and len(msg["parts"]) > 0]

payload = {"contents": clean_history}

Как исправить: Перед отправкой запроса пройдитесь по массиву contents и отфильтруйте все элементы, у которых parts является пустым списком или содержит пустые объекты.

Причина 5: Ошибка в регистре имён полей JSON в REST API запросе

Имена полей JSON в Gemini API используют camelCase (верблюжий регистр) и чувствительны к регистру. Опечатка в имени поля приведёт к его игнорированию, что равносильно передаче пустых данных.

Неправильное имя поля Правильное имя поля Объяснение
inline_data inlineData REST API использует camelCase
mime_type mimeType REST API использует camelCase
file_uri fileUri REST API использует camelCase
response_modalities responseModalities REST API использует camelCase
image_config imageConfig REST API использует camelCase
aspect_ratio aspectRatio REST API использует camelCase
image_size imageSize REST API использует camelCase

Неправильный код:

# ❌ В REST API использован snake_case (стиль Python SDK)
payload = {
    "contents": [{
        "parts": [{
            "inline_data": {           # ← Должно быть inlineData
                "mime_type": "image/png",   # ← Должно быть mimeType
                "data": image_b64
            }
        }]
    }],
    "generation_config": {             # ← Должно быть generationConfig
        "response_modalities": ["IMAGE"]   # ← Должно быть responseModalities
    }
}

Правильный код:

# ✅ REST API использует camelCase
payload = {
    "contents": [{
        "parts": [{
            "inlineData": {
                "mimeType": "image/png",
                "data": image_b64
            }
        }]
    }],
    "generationConfig": {
        "responseModalities": ["IMAGE"],
        "imageConfig": {
            "aspectRatio": "1:1",
            "imageSize": "2K"
        }
    }
}

🎯 Важное замечание: Python SDK (google-genai) использует snake_case (например, inline_data), а прямой вызов REST API использует camelCase (например, inlineData). При вызове через сервисы-прокси, такие как APIYI apiyi.com, используется формат REST API, поэтому необходимо применять camelCase.

Причина 6: Неподдерживаемый формат изображения или повреждённый файл

Переданные данные base64 для изображения могут быть корректными, но сам формат изображения не поддерживается, или файл повреждён.

Поддерживаемые форматы изображений для Gemini:

Формат mimeType Статус поддержки
PNG image/png Поддерживается
JPEG image/jpeg Поддерживается
WebP image/webp Поддерживается
GIF image/gif Частичная поддержка (только первый кадр)
BMP image/bmp Не поддерживается
SVG image/svg+xml Не поддерживается
TIFF image/tiff Не поддерживается

Метод проверки:

import base64

# Проверка валидности данных base64
def validate_image_data(b64_string, mime_type):
    # 1. Проверка на пустоту
    if not b64_string:
        print("ERROR: base64 data is empty")
        return False

    # 2. Проверка на наличие префикса data URI
    if b64_string.startswith("data:"):
        print("ERROR: Remove 'data:image/...;base64,' prefix")
        return False

    # 3. Проверка возможности декодирования base64
    try:
        decoded = base64.b64decode(b64_string)
        print(f"OK: Decoded size = {len(decoded)} bytes")
    except Exception as e:
        print(f"ERROR: Invalid base64 - {e}")
        return False

    # 4. Проверка поддержки mimeType
    supported = ["image/png", "image/jpeg", "image/webp", "image/gif"]
    if mime_type not in supported:
        print(f"ERROR: Unsupported mimeType '{mime_type}'")
        return False

    print("PASS: Image data is valid")
    return True

💡 Совет: Добавьте функцию валидации данных перед отправкой запроса — это поможет заранее отловить большинство проблем с форматом. Это также применимо при вызове через платформу APIYI apiyi.com.


Полный чек-лист для устранения ошибок в моделях изображений Gemini

Если вы столкнулись с ошибкой required oneof field 'data', последовательно проверьте каждый пункт из этого списка:

gemini-image-api-required-oneof-field-data-error-fix-ru 图示

Шаг проверки Что проверять Как исправить
Шаг 1 Посмотрите, какой по счёту элемент в parts[N] Напрямую перейдите к соответствующему месту в коде
Шаг 2 Пустой ли этот элемент: {}, null, "" Удалите пустой элемент или заполните его валидным содержимым
Шаг 3 Если это inlineData, не пустой ли base64 Убедитесь, что файл изображения успешно прочитан
Шаг 4 Содержит ли base64 префикс data: Удалите префикс, оставьте только чистый base64
Шаг 5 Используется ли camelCase для имён полей JSON В REST API обязательно используйте inlineData, а не inline_data
Шаг 6 Поддерживается ли формат изображения Только PNG/JPEG/WebP/GIF

Быстрое решение: Если вы часто сталкиваетесь с этой ошибкой на этапе разработки, рекомендую добавить функцию validate_payload() перед отправкой запроса, чтобы автоматически проверять валидность каждого элемента в массиве parts. При вызове моделей изображений Gemini через платформу APIYI apiyi.com, формат запроса полностью соответствует официальному REST API, поэтому описанные выше методы проверки также применимы.


Правильный формат запроса для Gemini Image Models при ошибках

Правильный формат для чистого текст-в-изображение (Text-to-Image)

import requests, base64

API_KEY = "your-apiyi-api-key"
ENDPOINT = "https://api.apiyi.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent"

# ✅ Минимальный правильный формат
payload = {
    "contents": [{
        "parts": [
            {"text": "A cute orange cat sitting on a windowsill, watercolor style, 4K"}
        ]
    }],
    "generationConfig": {
        "responseModalities": ["IMAGE"],
        "imageConfig": {
            "aspectRatio": "1:1",
            "imageSize": "2K"
        }
    }
}

response = requests.post(
    ENDPOINT,
    headers={"Content-Type": "application/json", "x-goog-api-key": API_KEY},
    json=payload,
    timeout=120
)

result = response.json()
image_data = result["candidates"][0]["content"]["parts"][0]["inlineData"]["data"]
with open("output.png", "wb") as f:
    f.write(base64.b64decode(image_data))

Правильный формат для изображение-в-изображение (Image-to-Image)

Показать полный правильный код для изображение-в-изображение
import requests
import base64
import pathlib

API_KEY = "your-apiyi-api-key"
ENDPOINT = "https://api.apiyi.com/v1beta/models/gemini-3.1-flash-image-preview:generateContent"

# Читаем исходное изображение и конвертируем в чистый base64
image_path = pathlib.Path("input_photo.png")
if not image_path.exists():
    raise FileNotFoundError(f"Image not found: {image_path}")

image_bytes = image_path.read_bytes()
image_b64 = base64.b64encode(image_bytes).decode("utf-8")

# Проверяем данные
assert len(image_b64) > 0, "Base64 data is empty"
assert not image_b64.startswith("data:"), "Remove data URI prefix"

# ✅ Правильный формат запроса для изображение-в-изображение
payload = {
    "contents": [{
        "parts": [
            {
                "inlineData": {
                    "mimeType": "image/png",
                    "data": image_b64
                }
            },
            {
                "text": "Change the background to a sunset beach scene, keep the subject unchanged"
            }
        ]
    }],
    "generationConfig": {
        "responseModalities": ["IMAGE"],
        "imageConfig": {
            "aspectRatio": "1:1",
            "imageSize": "2K"
        }
    }
}

response = requests.post(
    ENDPOINT,
    headers={"Content-Type": "application/json", "x-goog-api-key": API_KEY},
    json=payload,
    timeout=120
)

if response.status_code == 200:
    result = response.json()
    output_data = result["candidates"][0]["content"]["parts"][0]["inlineData"]["data"]
    with open("output_edited.png", "wb") as f:
        f.write(base64.b64decode(output_data))
    print("Success! Image saved.")
else:
    print(f"Error {response.status_code}: {response.text}")

Совет: Для сценариев текст-в-изображение начните с минимального формата, убедитесь, что он работает, а затем постепенно добавляйте параметры. Вызов Nano Banana 2 через платформу APIYI apiyi.com стоит $0.045 за раз, что делает отладку очень дешёвой.


Частые вопросы

В1: Что означает parts[2] в сообщении об ошибке?

parts[2] означает элемент с индексом 2 в массиве parts, то есть третий элемент (индексация начинается с 0). Просто найдите третий элемент в массиве contents[0].parts в своём коде и проверьте его содержимое. Если в вашем массиве parts всего 2 элемента (индексы 0 и 1), значит, в логике кода, возможно, случайно добавился пустой элемент при сборке массива.

В2: Эта ошибка возникает и при вызове через APIYI?

Да. APIYI apiyi.com, как сервис-прокси, передаёт ваш запрос напрямую в бэкенд Gemini. Если в теле запроса есть проблемы с форматом, бэкенд вернёт ту же ошибку 400. APIYI не изменяет структуру тела вашего запроса, поэтому обеспечение правильного формата — ответственность разработчика. Хорошая новость в том, что способ исправления точно такой же, как и при прямом вызове Google API.

В3: Почему имена полей в Python SDK и REST API отличаются?

Google GenAI Python SDK следует соглашению об именовании snake_case в Python (например, inline_data, mime_type). SDK внутри автоматически преобразует их в camelCase, требуемый API. Но если вы напрямую вызываете REST API с помощью библиотеки requests (включая вызовы через APIYI apiyi.com), вы должны вручную использовать формат camelCase (например, inlineData, mimeType). В противном случае поля будут проигнорированы, что приведёт к ошибке.

В4: Эта ошибка и ошибка «contents.parts must not be empty» — одно и то же?

Не совсем, но причина схожа. contents.parts must not be empty означает, что сам массив parts пуст ("parts": []), а required oneof field 'data' означает, что в parts есть элемент, но его поле данных не инициализировано (например, "parts": [{}]). Способ исправления одинаков: убедитесь, что каждый part содержит либо валидный text, либо inlineData.


Итог

Основные моменты ошибки required oneof field 'data' в модели изображений Gemini:

  1. Коренная причина: В массиве parts присутствуют пустые объекты, пустые данные или элементы с неверным форматом.
  2. Метод локализации: Используйте номер индекса parts[N] из сообщения об ошибке, чтобы напрямую найти соответствующее место в коде.
  3. Наиболее частые причины: Пустой объект {}, base64 с префиксом data:, ошибки в регистре имён полей JSON.
  4. Для REST API обязательно используйте camelCase: inlineData (не inline_data), mimeType (не mime_type).
  5. Меры предосторожности: Добавьте функцию валидации полезной нагрузки перед отправкой для автоматического обнаружения пустых элементов и проблем с форматом.

Рекомендуем использовать платформу APIYI apiyi.com для вызова модели изображений Gemini при разработке и отладке. Nano Banana 2 с оплатой за использование стоит $0.045/раз, что делает стоимость отладки крайне низкой. Формат интерфейса полностью совместим с официальным REST API.


📚 Справочные материалы

  1. Официальная документация по генерации изображений Gemini API: Полный формат запроса и описание параметров.

    • Ссылка: ai.google.dev/gemini-api/docs/image-generation
    • Описание: Содержит стандартные форматы запросов для Text-to-Image и Image-to-Image.
  2. Руководство по устранению неполадок Gemini API: Официальные коды ошибок и рекомендации по исправлению.

    • Ссылка: ai.google.dev/gemini-api/docs/troubleshooting
    • Описание: Охватывает методы устранения распространённых ошибок, таких как 400, 429, 500.
  3. GitHub Issue: Обсуждение ошибки required oneof field data: Сообщения от сообщества и варианты исправления.

    • Ссылка: github.com/google-gemini/cookbook/issues/786
    • Описание: Содержит подробный анализ и обходное решение (workaround) для этой ошибки, вызванной передачей объекта File.
  4. Документация по подключению APIYI Nano Banana 2: Полное руководство по вызову модели изображений Gemini на платформе APIYI.

    • Ссылка: docs.apiyi.com/en/api-capabilities/nano-banana-2-image
    • Описание: Содержит примеры правильного формата запроса и ответы на часто задаваемые вопросы.

Автор: Техническая команда APIYI
Техническое обсуждение: Если у вас возникли проблемы с вызовом Gemini API, добро пожаловать в центр документации APIYI docs.apiyi.com, чтобы ознакомиться с другими руководствами по устранению неполадок.

Похожие записи