abi: bump default Limits to accommodate ~100MB chain payloads#23
Merged
Conversation
Production sentinel (theater) hit "Sequence too large at node 2" when a child mailbox-actor on restore read a stored email message via the `store` host function. The chain-event recording embeds the full input and output of every wasm-call, so the message body (1.3MB in the observed case) flows through `theater:simple/supervisor-handlers.handle-child-event` as a `list<u8>` parameter. That `list<u8>` encodes as a single Array node with a count field of length-N, which trips `max_sequence_len: 1_000_000`. Bump the defaults: - max_buffer_size: 16 MB → 256 MB - max_node_count: 1 M → 10 M - max_payload_size: 8 MB → 128 MB - max_sequence_len: 1 M → 128 M These remain safety bounds (a runaway actor still can't produce arbitrarily large payloads), just sized for real-world email-class chain events. Follow-up: surface Limits as configuration on the host side so each embedder can tune the ceiling for its workload, instead of relying on a single hard-coded default. Worth its own design pass.
colinrozzi
added a commit
that referenced
this pull request
Jun 4, 2026
PR #23 bumped Limits::default in crates/pack-abi/src/lib.rs but the packr root crate (src/abi/mod.rs) has its own duplicate Limits struct and was missed. The downstream theater::pack_bridge::decode_value goes through packr::decode → packr::abi::Limits::default, so it kept seeing the pre-#23 limits and continued to reject ~1.3MB chain-event payloads with "Sequence too large at node 2". Mirror the same bump here so they stay in lockstep: - max_buffer_size: 16 MB → 256 MB - max_node_count: 1 M → 10 M - max_payload_size: 8 MB → 128 MB - max_sequence_len: 1 M → 128 M Follow-up: the two Limits structs should be consolidated — having packr re-export packr_abi::Limits would prevent this exact class of drift. Out of scope here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Production sentinel (downstream theater runtime) hits `InvalidEncoding("Sequence too large at node 2")` whenever a child mailbox-actor reads a stored email out of `store` on restore. Theater records every wasm-call's full input + output as a chain event, and the supervisor handler forwards that chain event to the parent via `handle-child-event(child-id, event-type, event-data: list)`. `event-data` of size N encodes as a single `NodeKind::Array` with count=N, which trips the decoder's `max_sequence_len: 1_000_000` ceiling for the observed 1,368,663-byte message.
The bump
These are still safety bounds — a pathological actor can't drive packr to allocate arbitrarily — just sized for real chain payloads from email-class workloads. Encode path was already unbounded (it's the decode that hits the wall); this brings decode in line.
Follow-up
Long-term: surface `Limits` as host-level configuration so each embedder can dial the ceiling for its workload, rather than living off a hard-coded default. Worth its own design pass.
🤖 Generated with Claude Code