Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Gemini API method models.generateContent returns error code 400 with Content Part "file_data"

In the last few hours, my app and a sample script from the documentation using Gemini API method models.generateContent started getting error code 400, "Request contains an invalid argument."  

The problem seems to be that the API is no longer accepting Content Part "file_data", though it accepts "inline_data".  Below I've inserted the example script "generatecontent.sh", copied directly from the documentation, which uploads the file to Gemini and then passes the file's URI to models.generateContent using "file_data". The script returns error code 400: 

 

$ ./generatecontent.sh test-small.jpg 
file_uri="https://generativelanguage.googleapis.com/v1beta/files/v2qx1k5plla2"
{
  "error": {
    "code": 400,
    "message": "Request contains an invalid argument.",
    "status": "INVALID_ARGUMENT"
  }
}

 

 

The script successfully uploaded the file:

 

curl "https://generativelanguage.googleapis.com/v1beta/files/v2qx1k5plla2?key=$GOOGLE_API_KEY"
{
  "name": "files/v2qx1k5plla2",
  "displayName": "TEXT",
  "createTime": "2024-11-12T00:23:43.810216Z",
  "updateTime": "2024-11-12T00:23:43.810216Z",
  "expirationTime": "2024-11-14T00:23:43.747497836Z",
  "uri": "https://generativelanguage.googleapis.com/v1beta/files/v2qx1k5plla2",
  "state": "ACTIVE"
}

 

I modified that script to use "inline_data" instead (also inserted below), and it executes without error:

 

$ ./generatecontent-inlinedata.sh test-small.jpg
{
  "candidates": [
    {
      "content": {
        "parts": [
          {
            "text": "There are no instruments in this photo. This appears to be a photo of a sunset over a grassy field. \n"
...

 

generatecontent.sh

 

# https://ai.google.dev/gemini-api/docs/vision?lang=rest

IMG_PATH_2="$1"
BASE_URL=https://generativelanguage.googleapis.com

MIME_TYPE=$(file -b --mime-type "${IMG_PATH_2}")
NUM_BYTES=$(wc -c < "${IMG_PATH_2}")
DISPLAY_NAME=TEXT

tmp_header_file=upload-header.tmp

# Initial resumable request defining metadata.
# The upload url is in the response headers dump them to a file.
curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \
  -D upload-header.tmp \
  -H "X-Goog-Upload-Protocol: resumable" \
  -H "X-Goog-Upload-Command: start" \
  -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
  -H "Content-Type: application/json" \
  -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null

upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")
rm "${tmp_header_file}"

# Upload the actual bytes.
curl "${upload_url}" \
  -H "Content-Length: ${NUM_BYTES}" \
  -H "X-Goog-Upload-Offset: 0" \
  -H "X-Goog-Upload-Command: upload, finalize" \
  --data-binary "@${IMG_PATH_2}" 2> /dev/null > file_info.json

file_uri=$(jq ".file.uri" file_info.json)
echo file_uri=$file_uri

# Now generate content using that file
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "contents": [{
        "parts":[
          {"text": "Can you tell me about the instruments in this photo?"},
          {"file_data":
            {"mime_type": "image/jpeg", 
            "file_uri": '$file_uri'}
        }]
        }]
       }' 2> curl-error.txt > response.json

cat response.json
echo

jq ".candidates[].content.parts[].text" response.json

 

 

generatecontent-inlinedata.sh

 

IMG_PATH_2="$1"
BASE_URL=https://generativelanguage.googleapis.com

MIME_TYPE=$(file -b --mime-type "${IMG_PATH_2}")
NUM_BYTES=$(wc -c < "${IMG_PATH_2}")
DISPLAY_NAME=TEXT

tmp_header_file=upload-header.tmp

# Now generate content using that file
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "contents": [{
        "parts":[
          {"text": "Can you tell me about the instruments in this photo?"},
          {"inline_data": 
            {"mime_type": "image/jpeg",
             "data": "'$(base64 -i $IMG_PATH_2)'"}
        }]
        }]
       }' 2> curl-error.txt > response.json

cat response.json
echo

jq ".candidates[].content.parts[].text" response.json

 

 

 

2 2 8,362
2 REPLIES 2

Thanks. And it looks like it was just fixed.