Skip to content

fix(callbacks/v2): OnTimeoutPacket blocked by UnmarshalPacketData error#8856

Merged
srdtrk merged 4 commits intocosmos:mainfrom
mefai-dev:fix/v2-callbacks-timeout-unmarshal-blocking
Mar 26, 2026
Merged

fix(callbacks/v2): OnTimeoutPacket blocked by UnmarshalPacketData error#8856
srdtrk merged 4 commits intocosmos:mainfrom
mefai-dev:fix/v2-callbacks-timeout-unmarshal-blocking

Conversation

@mefai-dev
Copy link
Copy Markdown
Contributor

OnTimeoutPacket propagates UnmarshalPacketData errors, blocking the packet timeout lifecycle. This is inconsistent with OnSendPacket (line 124) and OnAcknowledgementPacket (line 254), both of which return nil on the same error, allowing the packet lifecycle to continue unblocked.

The inconsistency is also visible in the comments:

  • OnSendPacket: "is not blocked if the packet does not opt-in to callbacks" (line 123)
  • OnAcknowledgementPacket: same comment (line 252)
  • OnTimeoutPacket: comment was missing (now added)

The V1 callbacks middleware does not have this inconsistency because it uses a different pattern (GetSourceCallbackData combining unmarshal and callback data extraction).

Impact: If a packet's payload cannot be unmarshalled by the callbacks middleware (e.g., codec version mismatch), the timeout transaction reverts entirely. The underlying app's OnTimeoutPacket has already executed the refund (line 317-320), but the revert rolls back all state changes. Since the packet has already timed out on the destination chain and cannot be received, the sender's funds become permanently locked with no recovery path.

This aligns with the principle stated at line 359: "callback execution errors are not allowed to block the packet lifecycle."

mefai-dev and others added 3 commits March 22, 2026 19:22
…utPacket

OnTimeoutPacket propagates UnmarshalPacketData errors, blocking the
packet timeout lifecycle. This is inconsistent with OnSendPacket
(line 124) and OnAcknowledgementPacket (line 254), both of which
return nil on the same error, allowing the packet lifecycle to
continue unblocked.

The inconsistency is also visible in the comments:
- OnSendPacket: "is not blocked if the packet does not opt-in to
  callbacks" (line 123)
- OnAcknowledgementPacket: same comment (line 252)
- OnTimeoutPacket: comment was missing (now added)

The V1 callbacks middleware does not have this inconsistency because
it uses a different pattern (GetSourceCallbackData combining unmarshal
and callback data extraction).

Impact: If a packet's payload cannot be unmarshalled by the callbacks
middleware (e.g., codec version mismatch), the timeout transaction
reverts entirely. The underlying app's OnTimeoutPacket has already
executed the refund (line 317-320), but the revert rolls back all
state changes. Since the packet has already timed out on the
destination chain and cannot be received, the sender's funds become
permanently locked with no recovery path.

This aligns with the principle stated at line 359: "callback execution
errors are not allowed to block the packet lifecycle."
@srdtrk srdtrk changed the title fix(callbacks/v2): return nil on UnmarshalPacketData error in OnTimeo… fix(callbacks/v2): OnTimeoutPacket blocked by UnmarshalPacketData error Mar 26, 2026
@srdtrk srdtrk enabled auto-merge (squash) March 26, 2026 15:21
@srdtrk srdtrk disabled auto-merge March 26, 2026 15:21
@srdtrk srdtrk merged commit 0e8a117 into cosmos:main Mar 26, 2026
1 check passed
mergify bot pushed a commit that referenced this pull request Mar 26, 2026
…or (#8856)

* fix(callbacks/v2): return nil on UnmarshalPacketData error in OnTimeoutPacket

OnTimeoutPacket propagates UnmarshalPacketData errors, blocking the
packet timeout lifecycle. This is inconsistent with OnSendPacket
(line 124) and OnAcknowledgementPacket (line 254), both of which
return nil on the same error, allowing the packet lifecycle to
continue unblocked.

The inconsistency is also visible in the comments:
- OnSendPacket: "is not blocked if the packet does not opt-in to
  callbacks" (line 123)
- OnAcknowledgementPacket: same comment (line 252)
- OnTimeoutPacket: comment was missing (now added)

The V1 callbacks middleware does not have this inconsistency because
it uses a different pattern (GetSourceCallbackData combining unmarshal
and callback data extraction).

Impact: If a packet's payload cannot be unmarshalled by the callbacks
middleware (e.g., codec version mismatch), the timeout transaction
reverts entirely. The underlying app's OnTimeoutPacket has already
executed the refund (line 317-320), but the revert rolls back all
state changes. Since the packet has already timed out on the
destination chain and cannot be received, the sender's funds become
permanently locked with no recovery path.

This aligns with the principle stated at line 359: "callback execution
errors are not allowed to block the packet lifecycle."

* docs: added deleted comment

* docs: added CHANGELOG entry

---------

Co-authored-by: srdtrk <srdtrk@hotmail.com>
(cherry picked from commit 0e8a117)

# Conflicts:
#	CHANGELOG.md
srdtrk added a commit that referenced this pull request Mar 26, 2026
…or (backport #8856) (#8870)

* fix(callbacks/v2): OnTimeoutPacket blocked by UnmarshalPacketData error (#8856)

* fix(callbacks/v2): return nil on UnmarshalPacketData error in OnTimeoutPacket

OnTimeoutPacket propagates UnmarshalPacketData errors, blocking the
packet timeout lifecycle. This is inconsistent with OnSendPacket
(line 124) and OnAcknowledgementPacket (line 254), both of which
return nil on the same error, allowing the packet lifecycle to
continue unblocked.

The inconsistency is also visible in the comments:
- OnSendPacket: "is not blocked if the packet does not opt-in to
  callbacks" (line 123)
- OnAcknowledgementPacket: same comment (line 252)
- OnTimeoutPacket: comment was missing (now added)

The V1 callbacks middleware does not have this inconsistency because
it uses a different pattern (GetSourceCallbackData combining unmarshal
and callback data extraction).

Impact: If a packet's payload cannot be unmarshalled by the callbacks
middleware (e.g., codec version mismatch), the timeout transaction
reverts entirely. The underlying app's OnTimeoutPacket has already
executed the refund (line 317-320), but the revert rolls back all
state changes. Since the packet has already timed out on the
destination chain and cannot be received, the sender's funds become
permanently locked with no recovery path.

This aligns with the principle stated at line 359: "callback execution
errors are not allowed to block the packet lifecycle."

* docs: added deleted comment

* docs: added CHANGELOG entry

---------

Co-authored-by: srdtrk <srdtrk@hotmail.com>
(cherry picked from commit 0e8a117)

# Conflicts:
#	CHANGELOG.md

* docs: fix conflict

---------

Co-authored-by: Mefai <95135443+mefai-dev@users.noreply.github.com>
Co-authored-by: srdtrk <srdtrk@hotmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants