zeroclaw-labs/zeroclaw · error

WhatsApp interactive list capped at 10 sections (got {})

Error message

WhatsApp interactive list capped at 10 sections (got {})

What it means

Meta's interactive list messages allow at most 10 sections per message; `send_interactive_list` enforces this client-side and reports the offending count. No HTTP request is made. Related but distinct from the per-section row cap (10 rows, see the section-row error).

Source

Thrown at crates/zeroclaw-channels/src/whatsapp.rs:615

    /// Send an interactive list message (more than 3 options, up to 10
    /// rows per section, up to 10 sections per Meta's limits). `sections`
    /// each carry a section title + rows. Each row's `id` round-trips
    /// through the inbound `interactive.list_reply.id` as `[choice]<id>`.
    ///
    /// `button_text` is the button label that opens the list (Meta limits
    /// to 20 chars).
    pub async fn send_interactive_list(
        &self,
        recipient: &str,
        body_text: &str,
        button_text: &str,
        sections: &[InteractiveListSection],
    ) -> anyhow::Result<()> {
        if sections.is_empty() {
            anyhow::bail!("WhatsApp interactive list requires at least one section");
        }
        if sections.len() > 10 {
            anyhow::bail!(
                "WhatsApp interactive list capped at 10 sections (got {})",
                sections.len()
            );
        }
        for s in sections {
            if s.rows.len() > 10 {
                anyhow::bail!(
                    "WhatsApp interactive list section '{}' capped at 10 rows (got {})",
                    s.title,
                    s.rows.len()
                );
            }
        }
        let url = format!(
            "https://graph.facebook.com/v18.0/{}/messages",
            self.endpoint_id
        );
        ensure_https(&url)?;

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Merge or re-chunk sections until there are at most 10 (use chunks of up to 10 rows each, which supports 100 options in 10 sections).
  2. Split the content across multiple list messages.
  3. For flat option lists, call `send_choice(recipient, prompt, &options)` — it chunks 10 rows per section automatically and stays within both caps up to 100 options.

Example fix

// before: 15 category sections -> bails at the 10-section cap
channel.send_interactive_list(to, "Catalog:", "Browse", &by_category).await?;

// after: re-chunk into at most 10 sections of at most 10 rows
let sections: Vec<_> = all_rows
    .chunks(10)
    .enumerate()
    .map(|(i, c)| InteractiveListSection {
        title: format!("Items {}-{}", i * 10 + 1, i * 10 + c.len()),
        rows: c.to_vec(),
    })
    .collect();
channel.send_interactive_list(to, "Catalog:", "Browse", &sections).await?;
Defensive patterns

Strategy: validation

Validate before calling

const MAX_SECTIONS: usize = 10;
if sections.len() > MAX_SECTIONS {
    anyhow::bail!("{} sections exceeds WhatsApp's {}-section cap", sections.len(), MAX_SECTIONS);
}
channel.send_interactive_list(recipient, body, button_text, &sections).await

Type guard

fn within_section_cap(sections: &[InteractiveListSection]) -> bool {
    sections.len() <= 10
}

Prevention

When it happens

Trigger: Calling `send_interactive_list` with a `sections` slice of 11 or more entries — e.g. one section per category when a catalog has 15 categories, or chunking options into sections smaller than 10 rows so the section count balloons.

Common situations: Auto-generated catalogs or menus with many categories; chunking with a small chunk size (e.g. `chunks(5)` over 60 options yields 12 sections); assuming the library paginates for you — only `send_choice` chunks automatically, and it also caps at 10 sections.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/6e6c3a54d79b53ea. Report an issue: GitHub.