A decoder that uses `Bytes.Decode.fail` crashes instead of returning `Nothing`
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 48
- Forks
- 14
- Avg merge
- 4h 14m
- Merged PRs (30d)
- 1
Description
Found against: gren 0.6.6, gren-lang/core 7.4.2, node 22
Reproduction: in https://github.com/gilramir/gren-bug-reports, 2026-09-13-bytes-decode-fail; ./run.sh prints both runs
below.
Summary
src/Main.gren is the example from Bytes.Decode.fail's own documentation: a
tag byte picks a decoder, and an unknown tag is fail.
distance : Decode.Decoder String
distance =
Decode.unsignedInt8
|> Decode.andThen
(\tag ->
when tag is
0 -> Decode.map (\_ -> "yards") (Decode.float32 Bytes.BE)
1 -> Decode.map (\_ -> "meters") (Decode.float32 Bytes.BE)
_ -> Decode.fail
)
Decode.decode distance should give Nothing for an unknown tag. Instead the
program crashes.
| input | Decode.decode distance |
expected |
|---|---|---|
tag 0, then a float |
Just "yards" |
Just "yards" |
tag 0, then no float |
Nothing |
Nothing |
tag 7, then a float |
throws 0 |
Nothing |
fail is _Bytes_decodeFailure, which does throw 0. _Bytes_decode catches
only RangeError, the error a DataView read past the end raises, and rethrows
everything else:
var _Bytes_decode = F2(function (decoder, bytes) {
try {
return __Maybe_Just(A2(decoder, bytes, 0).__$value);
} catch (e) {
if (e instanceof RangeError) {
return __Maybe_Nothing;
} else {
throw e;
}
}
});
So running out of input is Nothing, and fail escapes as an uncaught 0. The
narrowing is commit 397368a, "Only return Nothing from Bytes.decode on RangeError
exceptions", first released in core 5.0.0. It
answers core#47 (elm/bytes#9), where a stack overflow inside a decoder came back
as Nothing.
Reproduction
./run.sh builds the program and runs it twice:
$ node app
known tag: Just yards
input too short: Nothing
exit status: 0
$ node app direct
0
exit status: 0
With no argument, each line is decoded inside its own task. The third line never
appears, stderr is empty and the exit status is 0. With direct, the same decode
runs outside any task, and node prints the thrown 0. The exit status is still 0.
That part is compiler#385 (a crashing program exits zero) and core#142 (an
exception raised after a stream write is swallowed), not this report
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run ./run.sh in the linked 2026-09-13-bytes-decode-fail reproduction and compare the two outputs. Then locate the _Bytes_decode entry point shown in the report and trace how Bytes.Decode.fail is handled alongside RangeError. Done means an unknown tag returns Nothing without changing the existing short-input behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100