Azure/azure-iot-sdk-csharp

[Bug Report] InvokeDeviceMethodAsync fails with error code 400000

williamiwell opened this issue · 4 comments

Context

  • OS, version, SKU and CPU architecture used: OSX/Ubuntu20.x (Windows 10 Desktop x64, Ubuntu 15.04 x86, Windows 10 IoT Core arm32, etc.)
  • Application's .NET Target Framework : dotnet 8 (See https://docs.microsoft.com/en-us/dotnet/standard/frameworks. E.g. netcoreapp2.1, net451, uap10.0, xamarin)
  • Device: - cloud (Laptop, Raspberry PI3, Android APIv25 etc.)
  • SDK version used: microsoft.azure.devices/1.39.1 (Please include the NuGet package version for all involved components)

Description of the issue

We use IotHub to send messages from our cloud to edge devices, using the InvokeDeviceMethodAsync method. This worked fine until 25-September-2024 19:00 UTC, but now we receive error code 400000. We can't find any information about this code, it's not listed in the common error codes docs.

We are using the latests nuget package: microsoft.azure.devices/1.39.1. The devices are online and are able to send device to cloud messages.

Any idea what is going on and if we can resolve this or that is related to an IotEdge issue?
Our IotHub is located in West Europa.

Code sample exhibiting the issue

var serviceClient = iotHubFactory.CreateServiceClient();
response = await serviceClient.InvokeDeviceMethodAsync(moduleId, cloudToDeviceMethod);

this throws the exception below:

{"Message":"{\"errorCode\":400000,\"message\":\"400\",\"trackingId\":\"46A2268BA66A4093B44234E2B56A6464-G2:-TimeStamp:2024-09-26T07:52:28.960569771Z\",\"timestampUtc\":\"2024-09-26T07:52:28.960569771Z\",\"info\":null}","ExceptionMessage":""}

Can you share a bit more about the direct method payload you are sending?

The payload is a json with protobuf base64 string, for example

{
"byteArrayBase64": "CiENAAB6RBIMCPKt1rcGEKiz05sBGgwIrq7WtwYQqLPTmwE="
}

The code below is used to set the payload:

var payloadJson = JsonConvert.SerializeObject(payload, jsonSerializerSettings);
cloudToDeviceMethod.SetPayloadJson(payloadJson);

Hello @williamiwell I was able to reproduce the issue and obtain the same error code.

Your call is missing a parameter, since I believe you are trying to invoke an edge custom module direct method, please add both the deviceId and the moduleId as parameters, this will enable the private function:

private static Uri GetModuleMethodUri(string deviceId, string moduleId)

to create the appropriate URL for the request to the API and call the method invocation for IoT edge module as mentioned in: https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-direct-methods#method-invocation-for-iot-edge-modules

Following the function expected parameters to invoke an edge custom module direct method,
Azure/azure-iot-sdk-csharp/blob/main/iothub/service/src/Messaging/ServiceClient.cs#L493

your call to the function should be similar to: (invoking the $edgeAgent ping method for reference, you can replace it with your custom module identity).

var methodInvocation = new CloudToDeviceMethod("ping") { ResponseTimeout = TimeSpan.FromSeconds(60), }; methodInvocation.SetPayloadJson("null");

CloudToDeviceMethodResult response = await serviceClient.InvokeDeviceMethodAsync(deviceId, "$edgeAgent", methodInvocation);

Executing this reference code I obtain from the CLI application:

Response status: 200, payload: null Press Enter to exit.

Hope the information is helpful, kind regards!

I can confirm that using two parameters works.

 // this works
 response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleName, cloudToDeviceMethod);
// the method below fails with a 400000 error code. 
var moduleId = $"{deviceId}/modules/{moduleName}";
response = await serviceClient.InvokeDeviceMethodAsync(moduleId, cloudToDeviceMethod);