LwM2M FOTA Download Stalls at 1–2% on nRF9160 over NB-IoT/LTE-M

I am using nRF9160 DK with nRF Connect SDK v2.9 and the LwM2M client sample (/samples/cellular/lwm2m_client/), converted from PSK to X.509 certificates.

The device connects successfully to my custom Leshan server on AWS, and works with Onomondo SIM cards. Security handshake with X.509 works fine after adjusting the server settings.

However, firmware update over-the-air (FOTA) fails:

  • The download starts and reports 1–2% progress.

  • After that, the download stalls and no more CoAP requests are observed on the server.

  • This happens even when testing with PSK against the demo LwM2M server.

  • Network connection seems stable, no obvious LTE disconnects, and device registration updates continue.

Also, on the server UI, I see it show me "Request Timeout."

[00:00:15.417,205] <inf> app_lwm2m_client: LwM2M is connected to server
[00:00:15.417,266] <inf> app_lwm2m_client: Obtained date-time from modem
[00:00:38.783,386] <inf> app_lwm2m_client: FOTA download started for instance 0
[00:00:38.784,667] <inf> lwm2m_firmware: Image type 1
[00:00:38.787,139] <inf> lwm2m_firmware: Application firmware download started.
[00:00:57.482,666] <inf> lwm2m_firmware: Downloaded 1%
[00:00:59.722,747] <inf> lwm2m_firmware: Downloaded 2%
[00:01:15.415,527] <dbg> app_lwm2m_client: rd_client_event: Registration update started
[00:01:15.810,852] <inf> net_lwm2m_rd_client: Update callback (code:2.4)
[00:01:15.810,882] <dbg> app_lwm2m_client: rd_client_event: Registration update complete
[00:01:15.810,974] <inf> net_lwm2m_rd_client: Update Done

CONFIG_LWM2M=y
CONFIG_LWM2M_COAP_BLOCK_SIZE=1024
CONFIG_LWM2M_COAP_MAX_MSG_SIZE=2048
CONFIG_LWM2M_CLIENT_UTILS=y
CONFIG_LWM2M_ENGINE_MAX_MESSAGES=15
CONFIG_LWM2M_ENGINE_MAX_PENDING=15
CONFIG_LWM2M_ENGINE_MAX_REPLIES=15

Questions:

  1. Is there a recommended configuration for LwM2M FOTA over NB-IoT/LTE-M for large firmware images?

  2. Should PSM/eDRX be disabled during FOTA, or is there a way to pause registration updates to avoid blocking the download?

  3. What are the recommended CoAP block sizes and engine parameters to reliably transfer large images?

  4. Are there known limitations when using Onomondo SIM + AWS Leshan for large firmware downloads?

Additional Info:

  • MCUboot v2.1.0

  • Zephyr OS v3.7.99

  • LTE-M/NB-IoT tested with Onomondo SIM

Parents
  • Hi.

    From the config you shared, I would first of all recommend you to try CONFIG_LWM2M_COAP_BLOCK_SIZE=512 and retest as there is a limitation mentioned here

    1. It is recommended to use pull delivery mode with CoAP or HTTP and starting from the lwm2m_client sample, enabling the overlay-fota_helper.conf overlay, which improves responsiveness in queue mode by using a 60-second update period.

    For large firmware downloads over LTE-M/NB-IoT, you may tune LwM2M queue-mode and timing parameters so the device stays online and listening long enough to complete the transfer. This includes increasing CONFIG_LWM2M_QUEUE_MODE_UPTIME, using a shorter CONFIG_LWM2M_UPDATE_PERIOD (similar to what overlay-fota_helper.conf does), and selecting an idle mode such as CONFIG_LWM2M_RD_CLIENT_LISTEN_AT_IDLE so the client keeps its socket open while the download is in progress.

    2. You do not have to disable PSM/eDRX for FOTA, as Nordic’s own lwm2m_client FOTA setup runs with PSM and eDRX enabled. However, aggressive PSM/eDRX or short queue-mode uptime can cause long block-wise transfers to stall. For large FOTA transfers, it is recommended to avoid very aggressive power-saving settings (like overlay-aggressive-psm.conf overlay file).

    And there are no specific limitations to Onomondo SIMs or AWS-hosted Leshan servers for LwM2M FOTA. You may try out the above mentioned configurations and check if it works.

    Best Regards,
    Syed Maysum

  •  i'am currently working on a FOTA implementation I am using nRF9160 DK with nRF Connect SDK  v3.1.1 and the LwM2M client sample (/samples/cellular/lwm2m_client/). I am using LwM2M with the Leshan server over the CoAP protocol.

    I am facing an issue: the app_update.bin file is no longer generated. I replaced it with zephyr.signed.bin in the update URL, but no FOTA update is triggered.

    this is my configuration 

    #MCUboot
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_BUILD_OUTPUT_BIN=y
    CONFIG_IMG_MANAGER=y
    CONFIG_MCUBOOT_IMG_MANAGER=y
    
    #Flash support
    CONFIG_FLASH=y
    CONFIG_FLASH_MAP=y
    CONFIG_STREAM_FLASH=y
    
    #LwM2M firmware object
    CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT=y
    
    CONFIG_POSIX_API=y
    
    # Allow FOTA downloads using download-client
    CONFIG_DOWNLOADER=y
    CONFIG_DOWNLOADER_STACK_SIZE=4096
    CONFIG_FOTA_DOWNLOAD=y

    Here are the logs I am getting

    00:07:16.822,967] fota_download_util: Download url https://xxxxxx/zephyr.signed.bin
    [00:07:16.823,028] fota_download_util: Download Path zephyr.signed.bin host https://leshan.xxxxxx
    [00:07:16.826,782] downloader: Host lookup failed for hostname leshan.xxxxxx on IPv6 (err -22), attempting IPv4
    [00:07:16.980,712] downloader: Setting up TLS credentials, sec tag count 1
    [00:07:16.980,834] downloader: Connecting to 91.134.59.209
    [00:07:18.089,569] downloader: Failed to connect, err -111
    [00:07:18.089,599] fota_download: Downloader error event -111
    [00:07:18.089,630] lwm2m_firmware: FOTA_DOWNLOAD_EVT_ERROR
    [00:07:18.089,630] lwm2m_firmware: FOTA download failed, target 0
    [00:07:18.092,742] app_lwm2m_client: FOTA failure 0 by status 4

    you can send me your configuration you added to upload FOTA 

    because i try and so manyt times and nothing works 

  • Hi,

    Your error indicates the downloader is attempting a TLS connection but failing. As the error -111 is ECONNREFUSED which means Connection refused that it indicates an error with the configured certificates. 

    So either no valid certificate is provisioned for the Leshan HTTPS server on the security tag or the certificate stored in the modem does not match the one the server presents

    So can you try this out:

    1. Get the CA certificate (or self signed cert) that the Leshan server uses for HTTPS. If Leshan is using a self signed certificate, you can extract it with:

    openssl s_client -showcerts -connect leshan.example.com:443

    2. Provision that CA certificate into a security tag in the modem. You can do this with the Cellular Monitor app or using modem_key_mgmt_write() with credential type MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN as shown here.

    3. Then add the Kconfig option that points the FOTA downloader to that security tag:

    CONFIG_LWM2M_CLIENT_UTILS_DOWNLOADER_SEC_TAG=<your_chosen_sec_tag>

    Best Regards,
    Syed Maysum

Reply
  • Hi,

    Your error indicates the downloader is attempting a TLS connection but failing. As the error -111 is ECONNREFUSED which means Connection refused that it indicates an error with the configured certificates. 

    So either no valid certificate is provisioned for the Leshan HTTPS server on the security tag or the certificate stored in the modem does not match the one the server presents

    So can you try this out:

    1. Get the CA certificate (or self signed cert) that the Leshan server uses for HTTPS. If Leshan is using a self signed certificate, you can extract it with:

    openssl s_client -showcerts -connect leshan.example.com:443

    2. Provision that CA certificate into a security tag in the modem. You can do this with the Cellular Monitor app or using modem_key_mgmt_write() with credential type MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN as shown here.

    3. Then add the Kconfig option that points the FOTA downloader to that security tag:

    CONFIG_LWM2M_CLIENT_UTILS_DOWNLOADER_SEC_TAG=<your_chosen_sec_tag>

    Best Regards,
    Syed Maysum

Children
  • The problem is that my device cannot find the app_update.bin file, and I don’t know how to properly configure the connection to access it

  • Hi,

    Looking at your logs, the issue is clear:

    downloader: Setting up TLS credentials, sec tag count 1
    downloader: Failed to connect, err -111

    You're using https:// in your firmware URI, but the modem can't establish TLS because no valid CA certificate is provisioned for that Leshan server. That's why it connects on TCP level (you can see it resolves the IP fine) but fails at the TLS handshake.

    You have two options:

    Option A (recommended, easiest, and most reliable over cellular)

    Switch to plain HTTP. Host the firmware on your server:

    bash
    cd ~/ota
    python3 -m http.server 8000

    Then in Leshan UI write to /5/0/1 (Package URI):

    http://<your-server-ip>:8000/zephyr.signed.bin

    Make sure port 8000 is open in your firewall/security group inbound rules.

    Option B — Keep HTTPS, provision the CA certificate

    bash
    openssl s_client -connect leshan.yourserver.com:443 </dev/null 2>/dev/null | openssl x509 -outform PEM > leshan_ca.pem

    Provision it into the modem at a security tag:

    modem_key_mgmt_write(1, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, cert, cert_len);

    And add to prj.conf:

    CONFIG_FOTA_DOWNLOAD_SEC_TAG=1

    Also regarding app_update.bin, atleast for me in newer NCS with sysbuild it's no longer generated. The equivalent file is build/app/zephyr/zephyr.signed.bin. It's the same MCUboot-signed OTA image, just renamed. Use it directly in your firmware URL.

    hope that ressolve your issue 

  • Hi,

    Just to clarify, app_update.bin is not missing. In newer NCS versions with sysbuild, it has been renamed to zephyr.signed.bin, found at build/<your_app_name>/zephyr/zephyr.signed.bin. That's the correct file to use in your firmware URL.

    However, the file name is not what's blocking the update. As mentioned in my previous reply, the download is failing due to the TLS certificate error (-111). The device can't connect to your HTTPS server because the server's CA certificate isn't provisioned in the modem.

    Could you try the steps I shared earlier, extracting the server certificate and provisioning it with CONFIG_LWM2M_CLIENT_UTILS_DOWNLOADER_SEC_TAG? or alternatively if you want a quicker way to test first then try switching to plain HTTP and host the firmware on server.

    Best Regards,
    Syed Maysum

  • Here is a summary of what i did :

    1. HTTP configuration (local server)
      I hosted the firmware using a local Python server:

    python -m http.server 8000

    The firmware URL used was:

    192.168.1.46:8000/zephyr.signed.bin

    However, the download fails with a connection error. After investigation, I believe this is because the device is connected over LTE, and therefore cannot access my local IP address (192.168.1.46).

    ,519] <inf> app_lwm2m_client: FOTA download started for instance 0
    [00:36:05.209,411] <inf> fota_download_util: Download url http://192.168.1.46:8000/zephyr.signed.bin
    [00:36:05.209,503] <inf> fota_download_util: Download Path zephyr.signed.bin host http://192.168.1.46:8000
    [00:36:05.213,226] <inf> downloader: Host lookup failed for hostname 192.168.1.46 on IPv6 (err -22), attempting IPv4
    [00:36:05.216,705] <inf> downloader: Connecting to 192.168.1.46
    [00:36:29.223,419] <err> downloader: Failed to connect, err -116
    [00:36:29.223,449] <err> fota_download: Downloader error event -116
    [00:36:29.223,480] <err> lwm2m_firmware: FOTA_DOWNLOAD_EVT_ERROR
    [00:36:29.223,480] <inf> lwm2m_firmware: FOTA download failed, target 0
    [00:36:29.231,842] <inf> app_lwm2m_client: FOTA failure 0 by status 4
    

    1. HTTPS configuration (with CA certificate)
      I extracted the CA certificate from the server and integrated it into the modem using:

    modem_key_mgmt_write()

    I also configured:

    CONFIG_LWM2M_CLIENT_UTILS_DOWNLOADER_SEC_TAG=1

    Despite this, the HTTPS download still fails.

    :03.343,597] <inf> app_lwm2m_client: FOTA download started for instance 0
    [00:04:03.344,299] <inf> fota_download_util: Download url https://leshan.egconnect.cloud/zephyr.signed.bin
    [00:04:03.344,360] <inf> fota_download_util: Download Path zephyr.signed.bin host https://leshan.egconnect.cloud
    [00:04:03.348,815] <inf> downloader: Host lookup failed for hostname leshan.egconnect.cloud on IPv6 (err -22), attempting IPv4
    [00:04:03.433,502] <inf> net_lwm2m_rd_client: Update callback (code:2.4)
    [00:04:03.433,563] <dbg> app_lwm2m_client: rd_client_event: Registration update complete
    [00:04:03.433,593] <inf> net_lwm2m_rd_client: Update Done
    [00:04:03.532,379] <inf> net_lwm2m_message_handling: Send done!
    [00:04:03.533,386] <inf> net_lwm2m_message_handling: Send done!
    [00:04:03.542,877] <inf> lwm2m_rai: Ongoing traffic, RAI disabled
    [00:04:04.537,719] <inf> downloader: Setting up TLS credentials, sec tag count 1
    [00:04:04.537,841] <inf> downloader: Connecting to 91.134.59.209
    [00:04:05.689,239] <err> downloader: Failed to connect, err -111
    [00:04:05.689,270] <err> fota_download: Downloader error event -111
    [00:04:05.689,300] <err> lwm2m_firmware: FOTA_DOWNLOAD_EVT_ERROR
    [00:04:05.689,300] <inf> lwm2m_firmware: FOTA download failed, target 0
    [00:04:05.691,406] <inf> app_lwm2m_client: FOTA failure 0 by status 4

    1. Root cause (suspected)
      It seems that the main issue is network accessibility:

    • The firmware is hosted on my local machine (192.168.x.x)

    • The device is connected via LTE

    • Therefore, it cannot reach the firmware server

    1. HTTP configuration (local server)

      ,519] <inf> app_lwm2m_client: FOTA download started for instance 0
      [00:36:05.209,411] <inf> fota_download_util: Download url http://192.168.1.46:8000/zephyr.signed.bin
      [00:36:05.209,503] <inf> fota_download_util: Download Path zephyr.signed.bin host http://192.168.1.46:8000
      [00:36:05.213,226] <inf> downloader: Host lookup failed for hostname 192.168.1.46 on IPv6 (err -22), attempting IPv4
      [00:36:05.216,705] <inf> downloader: Connecting to 192.168.1.46
      [00:36:29.223,419] <err> downloader: Failed to connect, err -116
      [00:36:29.223,449] <err> fota_download: Downloader error event -116
      [00:36:29.223,480] <err> lwm2m_firmware: FOTA_DOWNLOAD_EVT_ERROR
      [00:36:29.223,480] <inf> lwm2m_firmware: FOTA download failed, target 0
      [00:36:29.231,842] <inf> app_lwm2m_client: FOTA failure 0 by status 4

      I hosted the firmware using a local Python server:

    python -m http.server 8000

    The firmware URL used was:

    192.168.1.46:8000/zephyr.signed.bin

    but doesn't work

    1. HTTPS configuration (with CA certificate)
      I extracted the CA certificate from the server and integrated it into the modem using:

    modem_key_mgmt_write()

    I also configured:

    CONFIG_LWM2M_CLIENT_UTILS_DOWNLOADER_SEC_TAG=1

    Despite this, the HTTPS download still fails.

     
    :03.343,597] <inf> app_lwm2m_client: FOTA download started for instance 0
    [00:04:03.344,299] <inf> fota_download_util: Download url https://leshan.egconnect.cloud/zephyr.signed.bin
    [00:04:03.344,360] <inf> fota_download_util: Download Path zephyr.signed.bin host https://leshan.egconnect.cloud
    [00:04:03.348,815] <inf> downloader: Host lookup failed for hostname leshan.egconnect.cloud on IPv6 (err -22), attempting IPv4
    [00:04:03.433,502] <inf> net_lwm2m_rd_client: Update callback (code:2.4)
    [00:04:03.433,563] <dbg> app_lwm2m_client: rd_client_event: Registration update complete
    [00:04:03.433,593] <inf> net_lwm2m_rd_client: Update Done
    [00:04:03.532,379] <inf> net_lwm2m_message_handling: Send done!
    [00:04:03.533,386] <inf> net_lwm2m_message_handling: Send done!
    [00:04:03.542,877] <inf> lwm2m_rai: Ongoing traffic, RAI disabled
    [00:04:04.537,719] <inf> downloader: Setting up TLS credentials, sec tag count 1
    [00:04:04.537,841] <inf> downloader: Connecting to 91.134.59.209
    [00:04:05.689,239] <err> downloader: Failed to connect, err -111
    [00:04:05.689,270] <err> fota_download: Downloader error event -111
    [00:04:05.689,300] <err> lwm2m_firmware: FOTA_DOWNLOAD_EVT_ERROR
    [00:04:05.689,300] <inf> lwm2m_firmware: FOTA download failed, target 0
    [00:04:05.691,406] <inf> app_lwm2m_client: FOTA failure 0 by status 4
Related