diff --git a/iothub/device/src/Exceptions/IotHubClientErrorCode.cs b/iothub/device/src/Exceptions/IotHubClientErrorCode.cs index 27abbb3841..fa408b7f5b 100644 --- a/iothub/device/src/Exceptions/IotHubClientErrorCode.cs +++ b/iothub/device/src/Exceptions/IotHubClientErrorCode.cs @@ -72,7 +72,7 @@ public enum IotHubClientErrorCode /// Retrying with exponential back-off could resolve this error. For information on the IoT hub quotas and /// throttling, see . /// - Throttled, + Throttled = 429, /// /// The ETag in the request does not match the ETag of the existing resource. diff --git a/iothub/device/src/Exceptions/IotHubClientErrorResponseMessage.cs b/iothub/device/src/Exceptions/IotHubClientErrorResponseMessage.cs index 8b72d4e489..4e52233ff4 100644 --- a/iothub/device/src/Exceptions/IotHubClientErrorResponseMessage.cs +++ b/iothub/device/src/Exceptions/IotHubClientErrorResponseMessage.cs @@ -11,7 +11,7 @@ namespace Microsoft.Azure.Devices.Client internal class IotHubClientErrorResponseMessage { [JsonProperty("errorCode")] - internal string ErrorCode { get; set; } + internal int ErrorCode { get; set; } [JsonProperty("trackingId")] internal string TrackingId { get; set; } diff --git a/iothub/device/src/Transport/Mqtt/GetTwinResponse.cs b/iothub/device/src/Transport/Mqtt/GetTwinResponse.cs index c2597b3e35..6f36392963 100644 --- a/iothub/device/src/Transport/Mqtt/GetTwinResponse.cs +++ b/iothub/device/src/Transport/Mqtt/GetTwinResponse.cs @@ -30,6 +30,6 @@ internal class GetTwinResponse /// /// The error message if the request failed. /// - internal string Message { get; set; } + internal IotHubClientErrorResponseMessage ErrorResponseMessage { get; set; } } } diff --git a/iothub/device/src/Transport/Mqtt/MqttTransportHandler.cs b/iothub/device/src/Transport/Mqtt/MqttTransportHandler.cs index c20040aed2..6ec4ece945 100644 --- a/iothub/device/src/Transport/Mqtt/MqttTransportHandler.cs +++ b/iothub/device/src/Transport/Mqtt/MqttTransportHandler.cs @@ -639,9 +639,23 @@ public override async Task GetTwinAsync(CancellationToken cancel if (getTwinResponse.Status != 200) { - throw new IotHubClientException( - getTwinResponse.Message, - IotHubClientErrorCode.NetworkErrors); + // Check if we have an int to string error code translation for the service returned error code. + // The error code could be a part of the service returned error message, or it can be a part of the topic string. + // We will check with the error code in the error message first (if present) since that is the more specific error code returned. + if ((Enum.TryParse(getTwinResponse.ErrorResponseMessage.ErrorCode.ToString(), out IotHubClientErrorCode errorCode) + || Enum.TryParse(getTwinResponse.Status.ToString(), out errorCode)) + && Enum.IsDefined(typeof(IotHubClientErrorCode), errorCode)) + { + throw new IotHubClientException(getTwinResponse.ErrorResponseMessage.Message, errorCode) + { + TrackingId = getTwinResponse.ErrorResponseMessage.TrackingId, + }; + } + + throw new IotHubClientException(getTwinResponse.ErrorResponseMessage.Message) + { + TrackingId = getTwinResponse.ErrorResponseMessage.TrackingId, + }; } return getTwinResponse.Twin; @@ -727,18 +741,23 @@ public override async Task UpdateReportedPropertiesAsync(ReportedPropertie if (patchTwinResponse.Status != 204) { - if (Enum.TryParse(patchTwinResponse.ErrorResponseMessage.ErrorCode, out IotHubClientErrorCode errorCode)) + // Check if we have an int to string error code translation for the service returned error code. + // The error code could be a part of the service returned error message, or it can be a part of the topic string. + // We will check with the error code in the error message first (if present) since that is the more specific error code returned. + if ((Enum.TryParse(patchTwinResponse.ErrorResponseMessage.ErrorCode.ToString(), out IotHubClientErrorCode errorCode) + || Enum.TryParse(patchTwinResponse.Status.ToString(), out errorCode)) + && Enum.IsDefined(typeof(IotHubClientErrorCode), errorCode)) { throw new IotHubClientException(patchTwinResponse.ErrorResponseMessage.Message, errorCode) { - TrackingId = patchTwinResponse.ErrorResponseMessage.TrackingId + TrackingId = patchTwinResponse.ErrorResponseMessage.TrackingId, }; } throw new IotHubClientException(patchTwinResponse.ErrorResponseMessage.Message) { - TrackingId = patchTwinResponse.ErrorResponseMessage.TrackingId - }; ; + TrackingId = patchTwinResponse.ErrorResponseMessage.TrackingId, + }; } return patchTwinResponse.Version; @@ -1061,10 +1080,33 @@ private void HandleTwinResponse(MqttApplicationMessageReceivedEventArgs received if (status != 200) { + IotHubClientErrorResponseMessage errorResponse = null; + + // This will only ever contain an error message which is encoded based on service contract (UTF-8). + if (payloadBytes.Length > 0) + { + string errorResponseString = Encoding.UTF8.GetString(payloadBytes); + try + { + errorResponse = JsonConvert.DeserializeObject(errorResponseString); + } + catch (JsonException ex) + { + if (Logging.IsEnabled) + Logging.Error(this, $"Failed to parse twin patch error response JSON. Message body: '{errorResponseString}'. Exception: {ex}. "); + + errorResponse = new IotHubClientErrorResponseMessage + { + Message = errorResponseString, + }; + } + } + + // This received message is in response to an update reported properties request. var getTwinResponse = new GetTwinResponse { Status = status, - Message = Encoding.UTF8.GetString(payloadBytes), // The error message is encoded based on service contract, which is UTF-8. + ErrorResponseMessage = errorResponse, }; getTwinCompletion.TrySetResult(getTwinResponse); @@ -1104,7 +1146,7 @@ private void HandleTwinResponse(MqttApplicationMessageReceivedEventArgs received catch (JsonReaderException ex) { if (Logging.IsEnabled) - Logging.Error(this, $"Failed to parse Twin JSON: {ex}. Message body: '{Encoding.UTF8.GetString(payloadBytes)}'"); + Logging.Error(this, $"Failed to parse Twin JSON. Message body: '{Encoding.UTF8.GetString(payloadBytes)}'. Exception: {ex}."); getTwinCompletion.TrySetException(ex); } @@ -1128,7 +1170,7 @@ private void HandleTwinResponse(MqttApplicationMessageReceivedEventArgs received catch (JsonException ex) { if (Logging.IsEnabled) - Logging.Error(this, $"Failed to parse twin patch error response JSON: {ex}. Message body: '{errorResponseString}'"); + Logging.Error(this, $"Failed to parse twin patch error response JSON. Message body: '{errorResponseString}'. Exception: {ex}. "); errorResponse = new IotHubClientErrorResponseMessage {