Skip to content

abi: bump default Limits to accommodate ~100MB chain payloads#23

Merged
colinrozzi merged 1 commit into
mainfrom
bump-default-limits
Jun 4, 2026
Merged

abi: bump default Limits to accommodate ~100MB chain payloads#23
colinrozzi merged 1 commit into
mainfrom
bump-default-limits

Conversation

@colinrozzi

Copy link
Copy Markdown
Owner

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

Limit Before After
`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 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

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 colinrozzi enabled auto-merge (squash) June 4, 2026 02:59
@colinrozzi colinrozzi merged commit 1fa1399 into main Jun 4, 2026
2 checks passed
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant