Device shadow firmware update status not syncing to cloud after edge deployment

We’ve deployed firmware updates to 47 edge devices running ThingWorx 9.7, but the device shadow status isn’t reflecting in our cloud platform. The MQTT topic configuration appears correct (devices/shadow/update), and the payload schema matches our Thing template. However, when checking the shadow service permissions in Composer, we’re seeing intermittent 403 errors in the application logs.

The edge devices confirm successful firmware installation locally, but the cloud dashboard shows ‘Unknown’ status. We’ve verified the shadow update topic is publishing, and the JSON payload structure includes firmwareVersion, updateTimestamp, and status fields. Is there a known permission issue with shadow service writes in 9.7, or could this be related to our MQTT QoS settings?

I ran into something similar last month. Beyond permissions, check if your shadow payload schema includes the required metadata fields. ThingWorx expects a specific structure with _thingName and _shadowVersion in the root object. If those are missing, the shadow service silently rejects the update. Can you share a sample of the JSON your devices are publishing?

The 403 errors are a red flag here. Check your RemoteThing permissions specifically for the shadow update service. In ThingWorx 9.7, there’s a separate permission set for device shadow operations that’s often overlooked during initial setup. Navigate to the Thing definition and verify that the edge device identity has Execute permissions on the UpdateDeviceShadow service. Also, confirm your MQTT broker is configured with the correct authentication tokens that map to these permissions.

Adding to the MQTT topic discussion - make sure your QoS is set to at least 1 for shadow updates. QoS 0 can lead to message loss during network fluctuations, which would explain intermittent sync failures. We standardized on QoS 1 for all device shadow communications after experiencing similar issues in our manufacturing deployment.

Let me walk through the complete solution addressing all three areas:

MQTT Topic Configuration: Your topic path needs dynamic thing name routing. Update your edge device MQTT publisher to use: devices/{thingName}/shadow/update where {thingName} is replaced with the actual RemoteThing identifier. This allows the ThingWorx shadow service to properly route incoming messages.

Device Shadow Payload Schema: The payload must include required metadata fields. Here’s the corrected structure:

{
  "_thingName": "EdgeDevice_047",
  "_shadowVersion": 1,
  "state": {
    "reported": {
      "firmwareVersion": "2.4.1",
      "updateTimestamp": 1710515400,
      "status": "completed"
    }
  }
}

The state.reported wrapper is crucial - it tells ThingWorx this is the device’s current state, not a desired state command.

ThingWorx Shadow Service Permissions: In Composer, navigate to each RemoteThing definition and verify these permissions:

  1. Open the Thing’s Permissions tab
  2. Find your edge device runtime user/group
  3. Ensure Execute permission is granted on the UpdateDeviceShadow service
  4. Verify PropertyWrite permission on all shadow-synchronized properties
  5. Check that the MQTT connection user has the same permissions

For the 403 errors specifically, check your Application Key scope. If using App Keys for MQTT authentication, the key must have both Thing.UpdateShadow and Thing.WriteProperty permissions at the minimum. Navigate to Security > Application Keys and edit the key assigned to your edge devices.

Additional Recommendations:

  • Set MQTT QoS to 1 (at-least-once delivery) for shadow updates
  • Enable shadow service logging: Set com.thingworx.shadow logger to DEBUG level to troubleshoot any remaining issues
  • Implement retry logic on the edge side for failed shadow updates
  • Consider adding a heartbeat mechanism to detect shadow sync failures proactively

After implementing these changes, restart the MQTT connection on your edge devices and monitor the Application Log for successful shadow update confirmations. The cloud dashboard should start reflecting accurate firmware status within 30-60 seconds of device updates.

That’s definitely part of the problem. Your payload needs proper shadow metadata. Also verify the MQTT topic path includes the thing name as a variable. Should be something like devices/{thingName}/shadow/update rather than a static path. The shadow service uses that topic structure to route updates to the correct Thing instance. Without it, the platform can’t determine which device shadow to update.