Summary
A to_candid / from_candid round-trip traps with IDL error: byte read out of buffer when the decode target is a subtype that omits many of the record's fields, i.e. when the decoder has to skip a large number of trailing fields. The threshold is small — in our tests it appears at 213 skipped fields (212 decodes fine, 213 traps).
The blob itself is well-formed: decoding the same value back into its full type (no fields skipped) succeeds. Only the field-skipping path fails.
Steps to reproduce
Generate a record with N Nat fields, encode it, and decode it into the empty record {} (which forces every field to be skipped):
gen() { python3 -c "
n=$1
fields=';'.join('f%d = 0'%i for i in range(n))
types=';'.join('f%d : Nat'%i for i in range(n))
print('import Prim \"mo:⛔\";')
print('type Big = { '+types+' };')
print('let r : Big = { '+fields+' };')
print('let blob = to_candid (r);')
print('switch (from_candid blob : ?({})) { case (?_) Prim.debugPrint(\"ok\"); case null Prim.debugPrint(\"null\") };')
"; }
gen 212 > r212.mo # decodes: prints "ok"
gen 213 > r213.mo # traps: IDL error: byte read out of buffer
Run each with moc -wasi-system-api rNNN.mo -o rNNN.wasm && wasmtime rNNN.wasm.
Observed
| case |
result |
212 fields, decode as {} (skip all) |
ok |
213 fields, decode as {} (skip all) |
IDL error: byte read out of buffer |
213 fields, decode as the full Big (skip none) — control |
ok |
Expected
Decoding a Candid record into a subtype that omits fields should skip the extra fields and succeed, regardless of how many fields are skipped. The encode/decode round-trip of a legal value should never trap.
Notes
- Reproduces under both enhanced orthogonal persistence (default, memory64) and
--legacy-persistence (wasm32), at the same 213 boundary.
- Independent of the skipped fields' value type — observed identically with
Nat and Nat8 fields, and independent of the field payload sizes.
- Only the field-skipping path is affected; decoding the value into its full type is fine, which rules out the encoder.
Environment
moc source 1.14.1-42-ga7139f0719
wasmtime 45.0.2
Summary
A
to_candid/from_candidround-trip traps withIDL error: byte read out of bufferwhen the decode target is a subtype that omits many of the record's fields, i.e. when the decoder has to skip a large number of trailing fields. The threshold is small — in our tests it appears at 213 skipped fields (212 decodes fine, 213 traps).The blob itself is well-formed: decoding the same value back into its full type (no fields skipped) succeeds. Only the field-skipping path fails.
Steps to reproduce
Generate a record with N
Natfields, encode it, and decode it into the empty record{}(which forces every field to be skipped):Run each with
moc -wasi-system-api rNNN.mo -o rNNN.wasm && wasmtime rNNN.wasm.Observed
{}(skip all)ok{}(skip all)IDL error: byte read out of bufferBig(skip none) — controlokExpected
Decoding a Candid record into a subtype that omits fields should skip the extra fields and succeed, regardless of how many fields are skipped. The encode/decode round-trip of a legal value should never trap.
Notes
--legacy-persistence(wasm32), at the same 213 boundary.NatandNat8fields, and independent of the field payload sizes.Environment
mocsource1.14.1-42-ga7139f0719wasmtime 45.0.2