apollographql / apollo-ios

📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.
https://www.apollographql.com/docs/ios/
MIT License
3.88k stars 723 forks source link

Apollo crashes when fetching failed query from cache #910

Closed ldiqual closed 3 years ago

ldiqual commented 4 years ago

Apollo crashes while trying to deserialize a failed query from cache, if the response contains a null object.

The flow goes as follows:

Query

{
    "operationName": "currentUser",
    "query": "query currentUser {\n  currentUser {\n    __typename\n    ...UserResponse\n  }\n}fragment UserResponse on User {\n  __typename\n  id\n  createdAt\n  updatedAt\n  firstName\n  lastName\n  email\n  phoneNumber\n  picture {\n    __typename\n    ...PhotoAttachmentResponse\n  }\n  company {\n    __typename\n    ...CompanyResponse\n  }\n}fragment PhotoAttachmentResponse on PhotoAttachment {\n  __typename\n  name\n  url\n  type\n}fragment CompanyResponse on Company {\n  __typename\n  id\n  createdAt\n  updatedAt\n  name\n  phoneNumber\n  type\n  location {\n    __typename\n    ...LocationResponse\n  }\n  picture {\n    __typename\n    ...PhotoAttachmentResponse\n  }\n  metadata {\n    __typename\n    ...CompanyMetadataResponse\n  }\n}fragment LocationResponse on Location {\n  __typename\n  street1\n  street2\n  city\n  state\n  country\n  postalCode\n}fragment CompanyMetadataResponse on CompanyMetadata {\n  __typename\n  domains\n  domainSignup\n  subtrade\n}",
    "variables": null
}

Response

{
    "errors": [{
        "message": "Error: Object does not exist",
        "locations": [{
            "line": 2,
            "column": 3
        }],
        "path": ["currentUser"],
        "extensions": {
            "code": "INTERNAL_SERVER_ERROR"
        }
    }],
    "data": {
        "currentUser": null
    }
}

Crash

2019-11-18 15:02:28.306407-0800 App[29725:29722740] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000114be602e __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x0000000114a53b20 objc_exception_throw + 48
    2   Foundation                          0x000000011126e96e +[NSJSONSerialization JSONObjectWithData:options:error:] + 0
    3   App                         0x000000010f52aad0 $s11App3APIC20processGraphQlResult33_21589503A7FB2EFCE38612E5B9C9607FLL6result13operationNamex6Apollo0E14QLSelectionSet_p_SStKSeRzlF + 1072
    4   App                         0x000000010f52a562 $s11App3APIC7perform5query10PromiseKit0F0Cyq_Gx_t6Apollo12GraphQLQueryRzSeR_r0_lFq_4DataQzKcfU1_ + 418
    5   App                         0x000000010f52a693 $s11App3APIC7perform5query10PromiseKit0F0Cyq_Gx_t6Apollo12GraphQLQueryRzSeR_r0_lFq_4DataQzKcfU1_TA + 67
    6   PromiseKit                          0x0000000111f1c6b0 $s10PromiseKit8ThenablePAAE3map2on5flags_AA0A0Cyqd__GSo17OS_dispatch_queueCSg_8Dispatch0J13WorkItemFlagsVSgqd__1TQzKctlFyAA6ResultOyARGcfU_yycfU_ + 416
    7   PromiseKit                          0x0000000111ef97cd $sIeg_IeyB_TR + 45
    8   libdispatch.dylib                   0x00000001178af848 _dispatch_call_block_and_release + 12
    9   libdispatch.dylib                   0x00000001178b07b9 _dispatch_client_callout + 8
    10  libdispatch.dylib                   0x00000001178bcc9b _dispatch_main_queue_callback_4CF + 1212
    11  CoreFoundation                      0x0000000114b48df9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    12  CoreFoundation                      0x0000000114b43a59 __CFRunLoopRun + 2329
    13  CoreFoundation                      0x0000000114b42e16 CFRunLoopRunSpecific + 438
    14  Foundation                          0x00000001111ab87f -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 211
    15  Nimble                              0x0000000139dbedc5 $s6Nimble19AwaitPromiseBuilderC4wait_4file4lineAA0B6ResultOyxGSS_SSSutFyyXEfU1_ + 757
    16  Nimble                              0x0000000139db5a6c $sIg_Ieg_TR + 12
    17  Nimble                              0x0000000139db5ad1 $sIeg_IyB_TR + 17
    18  Nimble                              0x0000000139db0118 -[NMBExceptionCapture tryBlock:] + 56
    19  Nimble                              0x0000000139dbe870 $s6Nimble19AwaitPromiseBuilderC4wait_4file4lineAA0B6ResultOyxGSS_SSSutF + 784
    20  Nimble                              0x0000000139dc0f41 $s6Nimble9pollBlock0B8Interval07timeoutD04file4line6fnName10expressionAA11AwaitResultOySbGSd_SdSSSuSSSbyKctF + 641
    21  Nimble                              0x0000000139db7a94 $s6Nimble5async33_BDDDD35DBE3F3A5A3DA3D282465B23D1LL5style9predicate7timeout4poll6fnNameAA9PredicateVyxGAA16ExpectationStyleO_AKS2dSStlFAA0R6ResultVAA10ExpressionVyxGcfU_ + 1188
    22  Nimble                              0x0000000139dba38f $s6Nimble5async33_BDDDD35DBE3F3A5A3DA3D282465B23D1LL5style9predicate7timeout4poll6fnNameAA9PredicateVyxGAA16ExpectationStyleO_AKS2dSStlFAA0R6ResultVAA10ExpressionVyxGcfU_TA + 63
    23  Nimble                              0x0000000139e1e59a $s6Nimble9PredicateV9satisfiesyAA0B6ResultVAA10ExpressionVyxGKF + 90
    24  Nimble                              0x0000000139dfd2d0 $s6Nimble7execute___2to11description17captureExceptionsSb_AA14FailureMessageCtAA10ExpressionVyxG_AA16ExpectationStyleOAA9PredicateVyxGS2SSgSbtlF3runL_Sb_AGtylF + 560
    25  Nimble                              0x0000000139dfcf19 $s6Nimble7execute___2to11description17captureExceptionsSb_AA14FailureMessageCtAA10ExpressionVyxG_AA16ExpectationStyleOAA9PredicateVyxGS2SSgSbtlF + 1433
    26  Nimble                              0x0000000139db907c $s6Nimble11ExpectationV12toEventually_7timeout12pollInterval11descriptionyAA9PredicateVyxG_S2dSSSgtF + 988
    27  TimberTests                         0x0000000139bad117 $s11TimberTests8APITestsC4specyyFyycfU_ + 2903
    28  Quick                               0x0000000139f596d0 $s5Quick7ExampleC3runyyF + 2704
    29  Quick                               0x0000000139f5a48b $s5Quick7ExampleC3runyyFTo + 43
    30  Quick                               0x0000000139f51115 __60+[QuickSpec addInstanceMethodForExample:classSelectorNames:]_block_invoke + 133
    31  CoreFoundation                      0x0000000114bed1cc __invoking___ + 140
    32  CoreFoundation                      0x0000000114bea2df -[NSInvocation invoke] + 319
    33  XCTest                              0x0000000138d0fa21 __24-[XCTestCase invokeTest]_block_invoke.208 + 78
    34  XCTest                              0x0000000138d69b49 -[XCTestCase(Failures) performFailableBlock:testCaseRun:shouldInterruptTest:] + 57
    35  XCTest                              0x0000000138d69a67 -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 96
    36  XCTest                              0x0000000138d0f50a __24-[XCTestCase invokeTest]_block_invoke + 1153
    37  XCTest                              0x0000000138d0efe2 -[XCTestCase testContextPerformInScope:] + 211
    38  XCTest                              0x0000000138d0f07c -[XCTestCase invokeTest] + 137
    39  XCTest                              0x0000000138d10ded __26-[XCTestCase performTest:]_block_invoke_2 + 43
    40  XCTest                              0x0000000138d69b49 -[XCTestCase(Failures) performFailableBlock:testCaseRun:shouldInterruptTest:] + 57
    41  XCTest                              0x0000000138d69a67 -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 96
    42  XCTest                              0x0000000138d10d04 __26-[XCTestCase performTest:]_block_invoke.334 + 88
    43  XCTest                              0x0000000138d7d352 +[XCTContext runInContextForTestCase:block:] + 219
    44  XCTest                              0x0000000138d10473 -[XCTestCase performTest:] + 668
    45  XCTest                              0x0000000138d55997 -[XCTest runTest] + 57
    46  XCTest                              0x0000000138d0aa4a __27-[XCTestSuite performTest:]_block_invoke + 365
    47  XCTest                              0x0000000138d0a174 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 54
    48  XCTest                              0x0000000138d0a471 -[XCTestSuite performTest:] + 355
    49  XCTest                              0x0000000138d55997 -[XCTest runTest] + 57
    50  XCTest                              0x0000000138d0aa4a __27-[XCTestSuite performTest:]_block_invoke + 365
    51  XCTest                              0x0000000138d0a174 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 54
    52  XCTest                              0x0000000138d0a471 -[XCTestSuite performTest:] + 355
    53  XCTest                              0x0000000138d55997 -[XCTest runTest] + 57
    54  XCTest                              0x0000000138d0aa4a __27-[XCTestSuite performTest:]_block_invoke + 365
    55  XCTest                              0x0000000138d0a174 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 54
    56  XCTest                              0x0000000138d0a471 -[XCTestSuite performTest:] + 355
    57  XCTest                              0x0000000138d55997 -[XCTest runTest] + 57
    58  XCTest                              0x0000000138d8c2fe __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 171
    59  XCTest                              0x0000000138d8c401 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke.84 + 118
    60  XCTest                              0x0000000138d24793 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 588
    61  XCTest                              0x0000000138d8c0bd -[XCTTestRunSession runTestsAndReturnError:] + 623
    62  XCTest                              0x0000000138cedfd7 -[XCTestDriver runTestsAndReturnError:] + 456
    63  XCTest                              0x0000000138d795a4 _XCTestMain + 2484
    64  libXCTestBundleInject.dylib         0x000000010fcf1be7 __copy_helper_block_e8_32s + 0
    65  CoreFoundation                      0x0000000114b4904c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    66  CoreFoundation                      0x0000000114b487b8 __CFRunLoopDoBlocks + 312
    67  CoreFoundation                      0x0000000114b4361e __CFRunLoopRun + 1246
    68  CoreFoundation                      0x0000000114b42e16 CFRunLoopRunSpecific + 438
    69  GraphicsServices                    0x00000001198bdbb0 GSEventRunModal + 65
    70  UIKitCore                           0x0000000120efbb48 UIApplicationMain + 1621
    71  App                         0x000000010f3b597b main + 75
    72  libdyld.dylib                       0x0000000117931c25 start + 1
    73  ???                                 0x0000000000000005 0x0 + 5
designatednerd commented 4 years ago

Oof. Yeah this is related to #205, but we definitely should not be crashing here.

Quick question: Is currentUser marked as non-nullable in your schema? If it is, your server shouldn't return the null if there's an error - our codegen assumes that if something is marked non-nullable, it won't be null, ever, even in the event of an error.

However the more likely case is that it's not annotated at all, meaning it's nullable, and I'll have to take a closer look at what's going on here under the hood that's causing the crash.

ldiqual commented 4 years ago

@designatednerd Thanks for following up! currentUser is nullable (user is not created yet). I'm happy to provide a sample project if you'd like, though it's a bit involved to set up.

designatednerd commented 4 years ago

A sample project would be a big help if you have the time for it!

designatednerd commented 4 years ago

@ldiqual I'm cleaning up old issues and wanted to check in and see if you're still having this problem or had a chance to throw together a sample project for it. Please let me know. Thank you!

designatednerd commented 3 years ago

Since I haven't heard back for quite some time on this, I'm going to close this out since #205 basically covers this same ground. Thank you!