Skip to content

[BUG] Gemini provider missing 'items' field for ARRAY parameters #480

@kieranklaassen

Description

@kieranklaassen

Basic checks

  • I searched existing issues - related to JSON schema tool parameters #76 but focused specifically on Gemini arrays
  • I can reproduce this consistently
  • This is a RubyLLM bug, not my application code

What's broken?

The Gemini provider's format_parameters method does not include the required items field for ARRAY type parameters. According to the Gemini API documentation, array parameters MUST include an items property that specifies the data type of array elements.

This causes Gemini API to reject function declarations with array parameters:

Error: In context=('properties', 'personas'), array schema missing items.

Current behavior (v1.8.2)

The RubyLLM::Parameter class doesn't support an items attribute, and the Gemini provider formats arrays like this:

{
  type: "ARRAY",
  description: "Array of persona strings"
  # Missing: items field!
}

Expected behavior

According to Gemini API requirements, arrays should be formatted like:

{
  type: "ARRAY",
  description: "Array of persona strings",
  items: { type: "STRING" }  # Required!
}

How to reproduce

class MyTool < RubyLLM::Tool
  description "Test tool with array parameter"
  param :personas, type: :array, desc: "Array of persona strings"
  
  def execute(personas:)
    personas.join(", ")
  end
end

# Try to use with Gemini
client = RubyLLM::Client.new(model: "gemini-2.0-flash")
chat = client.chat.with_tools([MyTool.new])
chat.ask("List three personas") # Fails with "array schema missing items"

Proposed solution

  1. Add items parameter support to RubyLLM::Parameter:
class Parameter
  attr_reader :name, :type, :description, :required, :items

  def initialize(name, type: 'string', desc: nil, required: true, items: nil)
    @name = name
    @type = type
    @description = desc
    @required = required
    @items = items  # New!
  end
end
  1. Update RubyLLM::Tool.param to accept items:
def param(name, **options)
  parameters[name] = Parameter.new(name, **options)  # Already passes items through
end
  1. Update Gemini provider to format items for arrays:
def format_parameters(parameters)
  {
    type: 'OBJECT',
    properties: parameters.transform_values do |param|
      param_hash = {
        type: param_type_for_gemini(param.type),
        description: param.description
      }.compact

      # Add items field for arrays (required by Gemini)
      if param.type.to_s.downcase == "array" && param.respond_to?(:items)
        items_type = param.items || :string  # Default to string
        param_hash[:items] = { type: param_type_for_gemini(items_type) }
      end

      param_hash
    end,
    required: parameters.select { |_, p| p.required }.keys.map(&:to_s)
  }
end

Usage after fix

# Simple arrays (defaults to string)
param :names, type: :array, desc: "List of names"

# Explicit item types
param :personas, type: :array, items: :string, desc: "Array of persona strings"
param :scores, type: :array, items: :integer, desc: "Array of scores"
param :steps, type: :array, items: :object, desc: "Array of step objects"

Environment

  • Ruby version: 3.4.2
  • Ruby LLM: 1.8.2
  • Model: gemini-2.0-flash

Related issues

Notes

This is a critical bug for anyone using Gemini with tools that have array parameters. Currently, the only workaround is to monkeypatch the library.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions