pub fn require_non_empty<T, E>(
items: Vec<T>,
error: impl FnOnce() -> E,
) -> Result<Vec<T>, E>Expand description
Reject an empty content list, with the error the call site chose.
Message content is a Vec, so “no content” is representable in the type.
Most wires nevertheless reject it — a completion that carried no message and
no tool call is a provider defect, and a history message with no blocks has
nothing to send — and at least one call site depends on that rejection as
control flow rather than as a diagnostic.
These guards used to be a side effect of the non-empty container’s constructor, which meant every site borrowed the same context-free “cannot create with an empty vector”. Stated explicitly here, each site keeps its own message, which is where the useful detail lives.
Two rules for anyone extending this:
- It is mostly a guard for the response direction. Empty assistant
content is legal at the rig level — a tool-call-only turn, a truncated
stream — but a provider returning nothing where its protocol promises
content is malformed, and that is what most of these call sites detect.
Request-direction emptiness at the rig level is rejected once, at the
request boundary — but a few request-conversion sites also use this guard,
because non-empty rig content can still convert to zero wire blocks
(e.g. assistant content whose only parts have no representation on that
wire), and only the provider’s own conversion can see that. If your
request
TryFromcan drop parts, guard the converted list too. - The check is on the whole list, never on individual items. A visibly empty block can still carry data that must survive a round trip: reasoning signatures and encrypted reasoning attach to blocks whose text is empty. Emptiness is a property of the list, not of its members.