The API aborts every ~2 minutes on a 76 GiB allocation: scale-value preallocates a sequence from its declared length #10
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The deployed API has been in a crash loop since 2026-09-09T22:30:24Z. As of 2026-09-10T09:00Z, 316 aborts, all identical:
Every one is the same size — 82,014,765,760 bytes, 76.4 GiB — and the process survives about 114 seconds from start to abort.
Where the number comes from
std::mem::size_of::<scale_value::Value<u32>>()is 80, andSo this is
Vec::<Value<u32>>::with_capacity(1_025_184_572). Inscale-value 0.18.2,scale_impls/decode.rs:For a sequence,
remaining()is the SCALE compact length read straight out of the blob. The allocation happens before a single item is decoded, so the very step that would have caught the mismatch never runs. A blob that disagrees with the registry does not returnErr— it takes the process down.This is the case
CLAUDE.mdsays cannot happen:It does neither. And
decode_events(&blob).ok()atingest.rs:758cannot help:.ok()catches anErr, not an abort.What it breaks
Not itself the standings — see the companion issue on
fill_gap— but it caps every process lifetime at ~114 s, and any work that needs longer than that never finishes.Not yet known
Which call site feeds it the mismatched blob. Ruled out by local reproduction against the live chains:
Decode error: Codec error, and reproduces locally as a plainErrThe abort follows an
rpc endpoint failed overline by between 3 and 60 seconds in every cycle, which is suggestive and not yet conclusive.Release builds are stripped, so the cores are not usable:
eu-stackreportsNo DWARF information found, and systemd's own unwinder produces two junk frames. Getting the call site needs eitherRUST_BACKTRACE=1on the unit or a debug build.Fix, regardless of the call site
Do not let a length read out of a blob size an allocation. The blob is at most a few hundred KiB, and no sequence in it can have more items than it has bytes, so the honest cap is the remaining input length. Either clamp before calling
decode_as_type, or — cleaner — check the declared length against the input and returnRuntimeError::Decodewhen it cannot possibly fit. That turns this into exactly the loud, local failure the decoder is supposed to produce.Upstream is worth a report too, but we should not wait for it.