You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
description: A conceptual overview of XCM observability in Polkadot, covering message correlation, tracing, and debugging features in modern runtimes.
3
+
description: This conceptual overview of XCM observability in Polkadot covers message correlation, tracing, and debugging features in modern runtimes.
4
4
---
5
5
6
6
# XCM Observability
7
7
8
8
## Introduction
9
9
10
-
Cross-Consensus Messaging (XCM) powers interoperability across the Polkadot ecosystem, but tracing and debugging these flows across multiple chains is challenging.
10
+
Cross-Consensus Messaging (XCM) enables interoperability across the Polkadot ecosystem; however, tracing and debugging these flows across multiple chains is a challenging task. This overview introduces the observability features in modern Polkadot runtimes and the Polkadot SDK that make XCMs easier to trace and debug, including:
11
11
12
-
This guide introduces the observability features in modern Polkadot runtimes and the Polkadot SDK that make XCMs easier to trace and debug.
12
+
- The [`SetTopic([u8; 32])`](https://github.com/polkadot-fellows/xcm-format#settopic){target=\_blank} instruction and `message_id` to track XCMs across chains.
13
+
- The use of [`PolkadotXcm.Sent`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/enum.Event.html#variant.Sent){target=\_blank} and [`MessageQueue.Processed`](https://paritytech.github.io/polkadot-sdk/master/pallet_message_queue/pallet/enum.Event.html#variant.Processed){target=\_blank} events to correlate messages.
14
+
- Derived message ID workarounds for older runtimes.
15
+
- The use of indexers and Chopsticks replay to diagnose failed or incomplete XCMs.
13
16
14
-
You'll learn how to:
17
+
!!! tip
18
+
For a hands-on walkthrough, see the companion tutorial: [XCM Observability in Action](/tutorials/interoperability/xcm-observability-in-action){target=\_blank}.
15
19
16
-
- Use the [`SetTopic([u8; 32])`](https://github.com/polkadot-fellows/xcm-format#settopic){target=\_blank} instruction and `message_id` to track XCMs across chains
17
-
- Correlate messages through [`PolkadotXcm.Sent`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/enum.Event.html#variant.Sent){target=\_blank} and [`MessageQueue.Processed`](https://paritytech.github.io/polkadot-sdk/master/pallet_message_queue/pallet/enum.Event.html#variant.Processed){target=\_blank} events
18
-
- Apply derived message ID workarounds for older runtimes
19
-
- Diagnose failed or incomplete XCMs with indexers and Chopsticks replay
20
+
## Topic Register
20
21
21
-
For a hands-on walkthrough, see the companion tutorial: [XCM Observability in Action](/tutorials/interoperability/xcm-observability-in-action){target=\_blank}.
22
-
23
-
## Core Concepts
24
-
25
-
### What is `SetTopic`?
22
+
[`SetTopic([u8; 32])`](https://github.com/polkadot-fellows/xcm-format#settopic){target=\_blank} is an XCM instruction that sets a 32-byte topic register inside the message. The topic serves as a logical identifier, or `message_id`, for XCM, allowing you to group and trace related messages across chains.
26
23
27
24
When executing XCMs (via [`limited_reserve_transfer_assets`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/struct.Pallet.html#method.limited_reserve_transfer_assets){target=\_blank}, other extrinsics, or raw calls from the [`PolkadotXcm` pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/struct.Pallet.html){target=\_blank}) on system chains, the runtime automatically appends a [`SetTopic([u8; 32])`](https://github.com/polkadot-fellows/xcm-format#settopic){target=\_blank} instruction if one is missing.
28
25
29
-
-**[`SetTopic([u8; 32])`](https://github.com/polkadot-fellows/xcm-format#settopic){target=\_blank}** is an XCM instruction that sets a 32-byte topic register inside the message.
30
-
- The topic acts as a **logical identifier** (`message_id`) for the XCM, allowing you to group and trace related messages across chains.
31
-
32
-
⚠️ **Note:** When using [`WithUniqueTopic`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm_builder/struct.WithUniqueTopic.html){target=\_blank}, the topic ID is guaranteed to be unique if `WithUniqueTopic` automatically appends the `SetTopic` instruction. However, if the message already includes a `SetTopic` instruction, the uniqueness of the ID depends on the message creator and is not guaranteed.
26
+
!!! note
27
+
When using [`WithUniqueTopic`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm_builder/struct.WithUniqueTopic.html){target=\_blank}, the topic ID is guaranteed to be unique if `WithUniqueTopic` automatically appends the `SetTopic` instruction. However, if the message already includes a `SetTopic` instruction, the uniqueness of the ID depends on the message creator and is not guaranteed.
33
28
34
-
###Observability Features
29
+
## Observability Features
35
30
36
-
Runtimes built from **`stable2503-5` or later** provide key observability features for tracing and correlating XCMs across chains:
31
+
Runtimes built from `stable2503-5` or later provide key observability features for tracing and correlating XCMs across chains:
37
32
38
-
-**[`PolkadotXcm.Sent`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/enum.Event.html#variant.Sent){target=\_blank}** emitted on the origin chain when an XCM is sent.
39
-
-**[`MessageQueue.Processed`](https://paritytech.github.io/polkadot-sdk/master/pallet_message_queue/pallet/enum.Event.html#variant.Processed){target=\_blank}** emitted on the destination chain when the XCM is processed.
40
-
- The **`message_id` in the `Sent` event matches the `id` in the `Processed` event**, enabling reliable cross-chain correlation. This `message_id` is derived from the `SetTopic` instruction.
33
+
-[**`PolkadotXcm.Sent`**](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/enum.Event.html#variant.Sent){target=\_blank}: Emitted on the origin chain when an XCM is sent.
34
+
-[**`MessageQueue.Processed`**](https://paritytech.github.io/polkadot-sdk/master/pallet_message_queue/pallet/enum.Event.html#variant.Processed){target=\_blank}: Emitted on the destination chain when the XCM is processed.
35
+
- The `message_id` in the `Sent` event matches the `id` in the `Processed` event, enabling reliable cross-chain correlation. This `message_id` is derived from the `SetTopic` instruction.
| Origin chain |`PolkadotXcm.Sent`|`message_id`| Identifies the sent XCM |
45
40
| Destination chain |`MessageQueue.Processed`|`id`| Confirms processing of the message |
46
41
47
-
Matching these IDs lets you **correlate** an origin message with its destination processing.
42
+
Matching these IDs allows you to correlate an origin message with its destination processing.
48
43
49
-
### Why Not `XcmpQueue.XcmpMessageSent`?
44
+
!!! question "Why not use `XcmpQueue.XcmpMessageSent`?"
45
+
The event [`XcmpQueue.XcmpMessageSent`](https://paritytech.github.io/polkadot-sdk/master/cumulus_pallet_xcmp_queue/pallet/enum.Event.html#variant.XcmpMessageSent){target=\_blank} contains a `message_hash` unrelated to `SetTopic`. It is not reliable for cross-chain tracing and should be avoided for observability purposes.
50
46
51
-
- The event [`XcmpQueue.XcmpMessageSent`](https://paritytech.github.io/polkadot-sdk/master/cumulus_pallet_xcmp_queue/pallet/enum.Event.html#variant.XcmpMessageSent){target=\_blank} contains a `message_hash` unrelated to `SetTopic`.
52
-
- It is **not reliable for cross-chain tracing** and should be avoided for observability purposes.
47
+
## Automatic vs Manual `SetTopic`
53
48
54
-
### Automatic vs Manual `SetTopic`
55
-
56
-
- The runtime **automatically appends a `SetTopic` instruction** if one is missing at the end of an XCM.
57
-
- When using high-level extrinsics such as `limited_reserve_transfer_assets`, **you do not need to set a topic manually**; the runtime handles it for you.
58
-
- If you **manually craft an XCM** (e.g., via [`execute`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/struct.Pallet.html#method.execute){target=\_blank} or [`send`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/struct.Pallet.html#method.send){target=\_blank}), you **can supply your own `SetTopic`**, but it **must be the final instruction** to be respected.
59
-
- In **multi-hop XCM flows**, manually setting the topic ensures **consistent tracing across all hops**. Any **remote XCM calls** embedded inside the XCM must also include a `SetTopic` at the end to preserve the same `message_id` throughout the cross-chain flow.
49
+
- The runtime automatically appends a `SetTopic` instruction if one is missing at the end of an XCM.
50
+
- When using high-level extrinsics such as `limited_reserve_transfer_assets`, you do not need to set a topic manually; the runtime handles it for you.
51
+
- If you manually craft an XCM (e.g., via [`execute`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/struct.Pallet.html#method.execute){target=\_blank} or [`send`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/struct.Pallet.html#method.send){target=\_blank}), you can supply your own `SetTopic`, but it must be the final instruction to be respected.
52
+
- In multi-hop XCM flows, manually setting the topic ensures consistent tracing across all hops. Any remote XCM calls embedded inside the XCM must also include a `SetTopic` at the end to preserve the same `message_id` throughout the cross-chain flow.
60
53
61
54
## Message Lifecycle
62
55
63
-
Here is a high-level overview of an XCM lifecycle with observability events:
56
+
The following is a high-level overview of an XCM lifecycle with observability events:
64
57
65
58
```mermaid
66
59
flowchart TD
@@ -81,13 +74,12 @@ flowchart TD
81
74
Origin --> Destination
82
75
```
83
76
84
-
* The `SetTopic` ensures a consistent `message_id` is passed and visible in these events.
85
-
* For multi-hop flows, the same `message_id` travels through all chains.
77
+
- The `SetTopic` ensures a consistent `message_id` is passed and visible in these events.
78
+
- For multi-hop flows, the same `message_id` travels through all chains.
86
79
87
80
## Workaround for Older Runtimes
88
81
89
-
* Runtimes prior to **`stable2503-5`** emit a **derived `forwarded_id`** instead of the original topic in downstream `Processed` events.
90
-
* The forwarded ID is calculated as:
82
+
Runtimes prior to `stable2503-5` emit a derived `forwarded_id` instead of the original topic in downstream `Processed` events. The forwarded ID is calculated as:
Common errors include missing assets, exceeded execution limits, or invalid asset locations. This nested error reporting, introduced in runtimes from **`stable2506` onward**, usually suffices to diagnose typical issues.
110
+
Common errors include missing assets, exceeded execution limits, or invalid asset locations. This nested error reporting, introduced in runtimes from `stable2506` onward, usually suffices to diagnose typical issues.
123
111
124
-
2.**Replay Using Chopsticks for Full Logs**
112
+
2.**Replay using Chopsticks for full logs**: For detailed troubleshooting, try the following steps:
125
113
126
-
For detailed troubleshooting:
114
+
- Replay the failing extrinsic with logging enabled.
115
+
- See exactly which instruction failed and why.
116
+
- View complete error chains like `FailedToTransactAsset` or `AssetNotFound`.
127
117
128
-
- Replay the failing extrinsic with logging enabled
129
-
- See exactly which instruction failed and why
130
-
- View complete error chains like `FailedToTransactAsset` or `AssetNotFound`
118
+
This approach is invaluable for multi-hop flows and complex custom XCMs.
131
119
132
-
This approach is invaluable for multi-hop flows and complex custom XCMs.
120
+
## Recommended Debugging Workflow
133
121
134
-
### Recommended Debugging Workflow
122
+
Follow these steps when debugging XCM failures:
135
123
136
-
1. Start with indexer or API error output
137
-
2. If unclear, use Chopsticks to replay the exact transaction
138
-
3. Inspect logs for the failing XCM instruction and reason
139
-
4. Adjust weight limits, asset locations, or message construction as needed
124
+
1. Start with indexer or API error output.
125
+
2. If unclear, use Chopsticks to replay the exact transaction.
126
+
3. Inspect logs for the failing XCM instruction and reason.
127
+
4. Adjust weight limits, asset locations, or message construction as needed.
140
128
141
-
→ See [Replay and Dry Run XCMs Using Chopsticks](/tutorials/interoperability/replay-and-dry-run-xcms/){target=\_blank} for replay instructions.
129
+
!!! tip
130
+
See [Replay and Dry Run XCMs Using Chopsticks](/tutorials/interoperability/replay-and-dry-run-xcms/){target=\_blank} for replay instructions.
142
131
143
132
## Best Practices
144
133
145
-
- When manually setting `SetTopic`, **always place it as the final instruction** in your XCM to ensure it is respected by the runtime.
146
-
- Prefer **automatic topic insertion** via high-level extrinsics for simplicity.
147
-
- If your use case involves multi-hop or custom XCMs, **manually set `SetTopic`** (including remote XCM calls) to guarantee consistent tracing.
148
-
- Ensure your `message_id` values are unique **if** you require deduplication or strict correlation.
134
+
- When manually setting `SetTopic`, always place it as the final instruction in your XCM to ensure it is respected by the runtime.
135
+
- Prefer automatic topic insertion via high-level extrinsics for simplicity.
136
+
- If your use case involves multi-hop or custom XCMs, manually set `SetTopic` (including remote XCM calls) to guarantee consistent tracing.
137
+
- Ensure your `message_id` values are unique if you require deduplication or strict correlation.
149
138
- When supporting legacy runtimes, be aware of the `forward_id_for` pattern.
0 commit comments