JS SDK: decoder crash on unknown field before an accumulated field

Decoding with Decoder.read({ includeUnknownData: true }) fails with:

"Cannot read properties of undefined (reading 'components')"

Decoding stops at that point, so all remaining messages in the file are lost.

Cause is in src/decoder.js, #setAccumulatedField() (line 719 in 21.213.0):

let components = messageDefinition.fields[containingField.fieldDefinitionNumber].components ?? []

With includeUnknownData: true, fields that have no Profile entry are present in message, so this lookup returns undefined. It only triggers when the unknown field comes before an accumulated field (distance, total_cycles, accumulated_power) in the message definition — the same fields in the opposite order decode fine.

Fix is the optional chaining already used on the next lookup two lines down:

let components = messageDefinition.fields[containingField.fieldDefinitionNumber]?.components ?? []

Reproduced on 21.208.0 and 21.213.0, Node 22. Happy to post a minimal repro script if that helps.

  • We will look into this. A minimal reproduction script would be useful, thanks.

  • Thanks for taking a look. I wrote up a minimal reproduction, but the forum's spam
    filter hid the post and the appeal was declined, so it never became visible. Happy to
    send it directly if there's a better channel, or to link a GitHub gist if links are
    allowed here.

    In the meantime the repro is short enough to describe in words. Build a FIT file with
    one record message (global mesg num 20) whose field definitions are, in this exact
    order:

    field 253, size 4, base type uint32 (timestamp)
    field 200, size 1, base type uint8 (not present in the profile)
    field 5, size 4, base type uint32 (distance -- isAccumulated in the profile)

    (Field 200 is only an example -- any field number with no entry in the record profile
    reproduces it. Note 200 IS defined in the session message, so it has to be a record.)

    Decode it with includeUnknownData: true. Because field 200 has no profile entry but is
    still added to the message, the lookup in #setAccumulatedField returns undefined and
    throws "Cannot read properties of undefined (reading 'components')". Decoding then
    stops, so every remaining message in the file is lost.

    Swap the order of field 5 and field 200 and the same file decodes cleanly -- when the
    accumulated field is read first, the unknown field isn't in the message yet.