Skip to content

[Bug]: empty multimodal messages are sent to the provider as a bare empty string #2676

Description

@1688mengdie

Problem

An empty multimodal message (no text and no images) built with
Message::user_multimodal("", vec![]) is converted through
impl From<Message> for AIMessage into content: Some("") - a bare empty
string sent straight to the provider. A strict API rejects it with a 400, and
a permissive gateway silently bills an empty request round.

Root cause

The Multimodal conversion arm has no empty-content guard. It starts content
from the text value and only appends attached-image markers when images are
present, then always wraps the result in Some(content). The Text and Mixed
arms both guard empty content (the Mixed arm returns None for empty text),
so the Multimodal arm is the only one without defence. The user_multimodal
constructor also does no validation, and serde deserialization rebuilds the
fields directly, so the conversion arm is the correct chokepoint to defend.

Repro

  1. Convert Message::user_multimodal(String::new(), vec![]) via AIMessage::from(...).
  2. Observe the resulting content is Some("") instead of None.

Impact

Empty request bodies reach the provider, causing 400 rejections on strict
providers or silent billing of empty rounds on permissive gateways.

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