aws-amplify / aws-sdk-ios

AWS SDK for iOS. For more information, see our web site:
https://aws-amplify.github.io/docs
Other
1.68k stars 885 forks source link

[IoT] list thing types failed with error "the timestamp value is invalid:<null>" #3539

Closed tom-xy closed 3 years ago

tom-xy commented 3 years ago

Describe the bug [IoT] list thing types failed with error the timestamp value is invalid:<null>

It only can be reproduced if one or more than one undeprecated thing types. If all thing types are deprecated, listing will be successful. Reason: JSON parsing process treats an optional value as required. Normal thing type(not deprecated) has no "deprecationDate".

To Reproduce Steps to reproduce the behavior:

  1. Create a thing type. (Do not deprecate it)
  2. Call "AWSIoT.default().listThingTypes"

Observed Behavior Error occurred

Expected Behavior List thing types successfully

Stack Trace None

Code Snippet

let request = AWSIoTListThingTypesRequest()!
        AWSIoT.default().listThingTypes(request).continueWith { (task) -> Any? in
            if let error = task.error {
                print("list thing types failed. \n\(error)")
            }
            if let items = task.result?.thingTypes {
                print("list thing types successfully. \(items.count)")
                var thingTypes: [String:IoTThingType] = [:]
                for item in items {
                    guard let name = item.thingTypeName, let arn = item.thingTypeArn else { continue }
                    let thingType = IoTThingType(id: nil, name: name, arn: arn)
                    thingType.definition = item
                    thingTypes[arn] = thingType
                }
                IoTCore.default.thingTypes = thingTypes
            }
            return nil
        }

Unique Configuration None

Areas of the SDK you are using (AWSMobileClient, Cognito, Pinpoint, IoT, etc)? AWSIoT

Environment(please complete the following information):

Device Information (please complete the following information):

Relevant Console Output

Error Domain=com.amazonaws.AWSTimestampSerializationErrorDomain Code=0 "the timestamp value is invalid:<null>" UserInfo={NSLocalizedDescription=the timestamp value is invalid:<null>}

CLI output

$ aws iot list-thing-types
{
    "thingTypes": [
        {
            "thingTypeName": "Phone",
            "thingTypeArn": "arn:aws:iot:eu-central-1:xxxxxx:thingtype/Phone",
            "thingTypeProperties": {},
            "thingTypeMetadata": {
                "deprecated": true,
                "deprecationDate": "2021-04-20T15:11:43.246000+08:00",
                "creationDate": "2021-04-20T14:47:22.721000+08:00"
            }
        }
    ]
}

{
    "thingTypes": [
        {
            "thingTypeName": "Phone",
            "thingTypeArn": "arn:aws:iot:eu-central-1:xxxxxx:thingtype/Phone",
            "thingTypeProperties": {},
            "thingTypeMetadata": {
                "deprecated": false,
                "creationDate": "2021-04-20T14:47:22.721000+08:00"
            }
        }
    ]
}
lawmicha commented 3 years ago

Hi @yutao86, sorry for the inconvenience caused. I was able to reproduce this, documenting the steps here

Pre-req

  1. Cognito Identity authenticated role has access to IoT actions

  2. Logging enabled in the app

    AWSDDLog.sharedInstance.logLevel = .verbose
    AWSDDLog.add(AWSDDTTYLogger.sharedInstance)
  3. On app launch, register AWSIoT using it's own AWSServiceConfiguration

    // initialize control plane
        let controlPlaneServiceConfiguration = AWSServiceConfiguration(region:AWSRegionType.USWest2, credentialsProvider: [CredentialsProvider]) 
        //IoT control plane seem to operate on iot.<region>.amazonaws.com
        AWSIoT.register(with: controlPlaneServiceConfiguration!, forKey: "MyAWSIoT")
  4. Sign in using the app

  5. Created a thing type in IoT console

Then i performed the API call with your code snippet,

amplifyIoTSample[81692:9913118] Response body:
{"nextToken":null,"thingTypes":[{"thingTypeArn":"arn:aws:iot:us-west-2:xxxxx:thingtype/thingTypename","thingTypeMetadata":{"creationDate":1.620049075277E9,"deprecated":false,"deprecationDate":null},"thingTypeName":"thingTypename","thingTypeProperties":{"searchableAttributes":null,"thingTypeDescription":"thing type descritpion"}}]}
list thing types failed. 
Error Domain=com.amazonaws.AWSTimestampSerializationErrorDomain Code=0 "the timestamp value is invalid:<null>" UserInfo={NSLocalizedDescription=the timestamp value is invalid:<null>}

It looks like when a thingtype is not deprecated, the deprecationDate is null, and is failing to deserialize to nil value.

lawmicha commented 3 years ago

This may be related and some of the code paths in this PR may be useful for debugging: https://github.com/aws-amplify/aws-sdk-ios/pull/3182

tom-xy commented 3 years ago

@lawmicha yes, deserialization failure. Should handle "deprecationDate" as an optional field.

dpwspoon commented 3 years ago

Not sure if this is the proper fix, but I was able to work around this by changing this line: https://github.com/aws-amplify/aws-sdk-ios/blob/2ce94a7fda175ed6ffd86c993b0ace219b926ac2/AWSCore/Serialization/AWSTimestampSerialization.m#L56

to

    if (!value || [value isEqual:[NSNull null]] || ![rules[@"type"] isEqualToString:@"timestamp"]) {

Note, this makes the return value the epochStart time and not null. Having it null would be ideal

lawmicha commented 3 years ago

I tested the API call with the branch from https://github.com/aws-amplify/aws-sdk-ios/pull/3587 and was able to get a successfully deserialized response:

2021-05-28 12:18:30:605 amplifyIoTSample[751:13822438] Response body:
{"nextToken":null,"thingTypes":[]}
list thing types successfully. 0
lawmicha commented 3 years ago

Hi @yutao86 we'll update this when https://github.com/aws-amplify/aws-sdk-ios/pull/3587 has been merged and released. In the meantime, if you're using pods, feel free to give it a try using that branch, ie.

  pod  'AWSIoT', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.nulltimestamp'
  pod  'AWSAuthCore', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.nulltimestamp'
  pod  'AWSCognitoIdentityProvider', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.nulltimestamp'
  pod  'AWSCognitoIdentityProviderASF', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.nulltimestamp'
  pod  'AWSMobileClient', :git => 'https://github.com/aws-amplify/aws-sdk-ios.git', :branch => 'royjit.nulltimestamp'
lawmicha commented 3 years ago

this has been released in https://github.com/aws-amplify/aws-sdk-ios/releases/tag/2.24.2 please let us know if you are still seeing issues