zeroclaw-labs/zeroclaw · error · anyhow::Error

matrix: selected single-message progress edit exceeds config

Error message

matrix: selected single-message progress edit exceeds configured message_max_bytes

What it means

In single-message progress mode the bot edits one message in place; edit() builds the replacement event via make_edit_event, serializes it, and enforces message_max_bytes. Unlike the threaded-reply path there is no iterative shrinking here - a single edit whose serialized event exceeds the budget aborts immediately. The usual driver is progress text that grows across edits (append-style summaries) until serialization crosses the cap.

Source

Thrown at crates/zeroclaw-channels/src/matrix.rs:3670

            ));
            let event = room
                .make_edit_event(event_id, EditedContent::RoomMessage(new_content))
                .await
                .map_err(|e| {
                    ::zeroclaw_log::record!(
                        ERROR,
                        ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
                            .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                            .with_attrs(::serde_json::json!({"error": format!("{}", e)})),
                        "make_edit_event failed"
                    );
                    anyhow::Error::msg(format!("make_edit_event failed: {e}"))
                })?;
            if let Some(max_bytes) = message_max_bytes {
                let actual =
                    serde_json::to_vec(&event).map_or(usize::MAX, |serialized| serialized.len());
                if actual > max_bytes {
                    anyhow::bail!(
                        "matrix: selected single-message progress edit exceeds configured message_max_bytes"
                    );
                }
            }
            event
        };
        room.send(edit_event).await?;
        Ok(candidate)
    }

    pub(super) async fn redact(
        client: &Client,
        room_id: &str,
        event_id: &OwnedEventId,
        reason: Option<String>,
    ) -> Result<()> {
        let room = client
            .get_room(&room_id.parse::<OwnedRoomId>()?)

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Raise channels.matrix.message_max_bytes above the largest expected edit.
  2. Bound the progress text in agent code: cap the rendered summary and rotate or drop old lines instead of growing forever.
  3. If long content is expected, switch the room to multi-message mode, which splits output instead of failing one big edit.

Example fix

// before: the in-place edit grows without bound
let text = format!("{previous}\n{new_line}");
edit(&client, &room_id, &event_id, &text, message_max_bytes).await?;

// after: keep the edit body under the budget (envelope overhead included)
let text = if previous.len() + new_line.len() + 1 > BODY_BUDGET {
    new_line.clone() // restart the summary instead of overflowing the cap
} else {
    format!("{previous}\n{new_line}")
};
edit(&client, &room_id, &event_id, &text, message_max_bytes).await?;
Defensive patterns

Strategy: validation

Validate before calling

const EVENT_ENVELOPE_OVERHEAD: usize = 1024; // measure once for your homeserver

fn edit_fits_budget(text: &str, max_bytes: Option<usize>) -> bool {
    match max_bytes {
        None => true,
        Some(max) => text.len() + EVENT_ENVELOPE_OVERHEAD <= max,
    }
}

assert!(edit_fits_budget(&next_progress_text, config.message_max_bytes));

Prevention

When it happens

Trigger: single_message mode with a configured message_max_bytes where make_edit_event produces an event larger than the cap - the accumulated progress text plus event envelope and the edited-content relation outgrew the budget.

Common situations: Progress messages appending a line per step until they exceed the cap; tightening message_max_bytes after deployment; Markdown inflation (bullet lists, code fences) as task output gets complex; long tool output quoted into the single message.

Related errors


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