TransferReassemblyErrorID.UNEXPECTED_TRANSFER_ID

Hi,

When is UNEXPECTED_TRANSFER_ID usually thrown? Context:

using Libcanard and BXCan on STM32 and Post-Mortem CAN Dump Analyzer to debug. Trying to answer to a GetInfo.1.0 Request

I will show you the human-readable .json of the candump:

{"_meta_": {"ts_system": 1743866278.796648, "ts_monotonic": 1364.192972352, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "optional", "transfer_id": 4, "source_node_id": 49, "destination_node_id": 125, "service_id": 430, "role": "request", "dtype": "uavcan.node.GetInfo.Request.1.0", "payload_hex": ""}}

and then (mixed with a couple heartbeat messages in between) TransferReassemblyErrorID.UNEXPECTED_TRANSFER_ID.

{"_meta_": {"ts_system": 1743866278.797218, "ts_monotonic": 1364.193137026, "transport": {"kind": "can", "source_iface": "can0"}, "error": "CANErrorTrace(timestamp=Timestamp(system_ns=1743866278797218000, monotonic_ns=1364193137026), error=<TransferReassemblyErrorID.UNEXPECTED_TRANSFER_ID: 3>)"}}
{"_meta_": {"ts_system": 1743866278.899989, "ts_monotonic": 1364.193852735, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "optional", "transfer_id": 6, "source_node_id": 33, "destination_node_id": null, "subject_id": 7510, "dtype": null, "payload_hex": "060000000102551d561d060000000102551d561d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000004000000000000000000000"}}
{"_meta_": {"ts_system": 1743866278.900267, "ts_monotonic": 1364.193924927, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 29, "source_node_id": 33, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "3d00000000003c"}, "uptime": 61, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 60}
{"_meta_": {"ts_system": 1743866279.070962, "ts_monotonic": 1364.19405874, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 13, "source_node_id": 49, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "cd00000000002a"}, "uptime": 205, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 42}
{"_meta_": {"ts_system": 1743866279.104825, "ts_monotonic": 1364.194189198, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 14, "source_node_id": 1, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "8e000000000016"}, "uptime": 142, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 22}
{"_meta_": {"ts_system": 1743866279.797341, "ts_monotonic": 1364.194317781, "transport": {"kind": "can", "source_iface": "can0"}, "error": "CANErrorTrace(timestamp=Timestamp(system_ns=1743866279797341000, monotonic_ns=1364194317781), error=<TransferReassemblyErrorID.UNEXPECTED_TRANSFER_ID: 3>)"}}
{"_meta_": {"ts_system": 1743866279.89335, "ts_monotonic": 1364.194376017, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 30, "source_node_id": 33, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "3e00000000003c"}, "uptime": 62, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 60}
{"_meta_": {"ts_system": 1743866280.078343, "ts_monotonic": 1364.194524186, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 14, "source_node_id": 49, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "ce00000000002a"}, "uptime": 206, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 42}
{"_meta_": {"ts_system": 1743866280.106402, "ts_monotonic": 1364.194658323, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 15, "source_node_id": 1, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "8f000000000016"}, "uptime": 143, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 22}
{"_meta_": {"ts_system": 1743866280.799132, "ts_monotonic": 1364.194788259, "transport": {"kind": "can", "source_iface": "can0"}, "error": "CANErrorTrace(timestamp=Timestamp(system_ns=1743866280799132000, monotonic_ns=1364194788259), error=<TransferReassemblyErrorID.UNEXPECTED_TRANSFER_ID: 3>)"}}
{"_meta_": {"ts_system": 1743866280.893382, "ts_monotonic": 1364.194846453, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 31, "source_node_id": 33, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "3f00000000003c"}, "uptime": 63, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 60}
{"_meta_": {"ts_system": 1743866281.071019, "ts_monotonic": 1364.194974466, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 15, "source_node_id": 49, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "cf00000000002a"}, "uptime": 207, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 42}
{"_meta_": {"ts_system": 1743866281.105233, "ts_monotonic": 1364.195106052, "transport": {"kind": "can", "source_iface": "can0"}, "priority": "nominal", "transfer_id": 16, "source_node_id": 1, "destination_node_id": null, "subject_id": 7509, "dtype": "uavcan.node.Heartbeat.1.0", "payload_hex": "90000000000016"}, "uptime": 144, "health": {"value": 0}, "mode": {"value": 0}, "vendor_specific_status_code": 22}
{"_meta_": {"ts_system": 1743866281.801047, "ts_monotonic": 1364.195233659, "transport": {"kind": "can", "source_iface": "can0"}, "error": "CANErrorTrace(timestamp=Timestamp(system_ns=1743866281801047000, monotonic_ns=1364195233659), error=<TransferReassemblyErrorID.UNEXPECTED_TRANSFER_ID: 3>)"}}

Obviously the message is verbose and tells me something is off with the transfer-ID. My logical order of functions is:

canPoll()
└── handle_getInfo_Request()
│       └── serialize_info_Response()
│       └── canardTxPush()
└── bxcan's bxCANPush() 
                [continues until canardTxPeek returns Null]

See bxCANPush() in bxcan.h line 152 Now the meta-data of the response is:

const CanardTransferMetadata transfer_metadata = {
        .priority       = CanardPriorityNominal,
        .transfer_kind  = CanardTransferKindResponse,
        .port_id        = uavcan_node_GetInfo_1_0_FIXED_PORT_ID_,
        .remote_node_id = requester_node_id,
        .transfer_id    = get_info_request_transfer_id,
};

based on Cyphal Specifictation.pdf p. 8/153 and 53/153:

Service response matching – when a server responds to a request, it uses the same transfer-ID for the response transfer as in the request transfer, allowing the client to emit concurrent requests to the same server
while being able to match each response with the corresponding local request state.

For the deadline in bxCANPush() I set values up to 100.000µs. When is UNEXPECTED_TRANSFER_ID usually thrown? It’s used a couple times in PyCyphal’s _transfer_reassembler.py, see _transfer_reassembler.py

Answer: see related git issue I should not have opened:

It means there is some transfer that is being repeatedly transmitted by some node with the same transfer-ID value. In your case, that value is three. You can find the offending transfer in the raw candump using the timestamps reported in the error traces; e.g., one is at system_ns=1743866281801047000.

by @pavel.kirienko