How to purge a scheduled confirmed downlink

Is it possible to purge a scheduled confirmed downlink in case the device does not acknowledge the downlink?

TTN will retransmit the downlink after each uplink as the device reboots before it acks. Of course the device should ack the downlink, but it doesn’t. Or we should stop using confirmed downlinks, but we do have a few devices in this (reboot) loop. How to break it?

I tried ttn-lw-cli end-devices downlink clear (edited), but that only works if the scheduled message hasn’t been tried to send to the device. I find it strange that ttn-lw-cli end-devices downlink list (edited) doesn’t show the downlink which the device gets over and over again.

Did you try the options in my post which you :heart: ??

It also refers to your last statement - I’d find it odd if I typed a command to get a list of devices and got back a list of downlinks.

1 Like

Ah, I made a typo in my post, I omitted the downlink keyword.

You wrote:

I think I ended up resetting the MAC state after it had joined but before it had uplinked so it didn’t have a session so didn’t connect so didn’t get the downlink.

Sounds a bit flaky, but I’ll give it a try.

Really? Flakey how so, it resets the device. Bit brutal but as at the time I was clearing a reboot command that would always lead to a rejoin, clearing the MAC state wasn’t an issue.

And that would have been part of me figuring out the solution, the correct solution being provided in the quoted CLI command if you just need to clear the queue and want to leave the device online.


I’ve done some tests with confirmed downlinks which are not being acked by the device (for whatever reason).

  • When you schedule a confirmed downlink it will show up when you run a ttn-lw-cli end-devices downlink list.
  • When the device transmits an uplink, the downlink is sent to the device, and the ttn-lw-cli end-devices downlink list returns an empty list. This is also the case if the device did not acknowledge the downlink (!)
  • TTN will retransmit the confirmed downlink in reply of each device uplink, as long as the device doesn’t ack.
  • When a device rejoins, TTN keeps retransmitting these downlinks (!)
  • When you schedule a new downlink, even with ttn-lw-cli end-devices downlink replace, the pending downlink is not removed and will be retransmitted again (!)

The only way to get rid of this confirmed non-acked downlink, is to either:

  • let the device ack the downlink (duhhh)
  • issue a ttn-lw-cli end-devices reset

In the later case the device must detect the session vanished and must rejoin. I was hoping that we could flush such a downlink without loosing the network session at TTN.

@kersing wrote that using confirmed downlinks is considered bad practice (How to clear downlink queue programmatically? - #4 by kersing), although I could not find posts explaining why.

1 Like

Simples…every time a GW transmits your or another users downlink it goes deaf to ALL other users uplinks for the duration. As you have seen using confirmed downlinks if something goes wrong it may just keep trying…vastly exacerbating the problem and potentially perpetuating it until cleared. Also, as a Radiator itself, in many parts of the world the GW’s also have a TX duty cycle limit, which if reached will remove key GW functionaity until channels ‘free’ again - stopping other devices receiving e.g. Join info, ADR updates etc…Obvious really!

For this reason there is a downlink limit (confirmed or otherwise) of 10 DL/day/device, including e.g. Join Accepts, system generated MAC commands, etc., though a simple search and read of the forum will tell you we consider that to be extreme use on the Community network…think more like 10 per week, maybe even 10 per month!

If your application is dependent on frequent DLs (or the other potential sin of regular confirmed uplinks - that then trigger a corresponding downlink!) the Community network may not be the best place for you - consider a self hosted, TTI hosted, or enterprise instance of TTS so you can work ‘privately’, without impacting other TTN users…

There are a number of discussions where this is explained, in short:
Confirmed downlinks depend on all uplinks to get through. If the uplink with the ack is missed there will be another downlink with whatever data was sent before. Now your embedded device needs to deduplicate those downlinks or process the same information twice.
Then there is the issue you encountered where the downlink causes the device to reset (the stack or all of it doesn’t matter) so no ack will ever be arriving. You are stuck in a loop…

The best way to handle downlink acknowledgment is at application level. When a downlink is received and handled update a field that will be in all your uplinks so even if a couple of uplinks are missed your application still knows the device got its instructions and processed them.


Just leaving this here, as it will help find the correct command: