Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix to handle invalid API directions #450

Merged
merged 1 commit into from
Sep 2, 2020

Conversation

hunterlindsay
Copy link
Contributor

@hunterlindsay hunterlindsay commented Aug 28, 2020

Background

On Thursday the 20th (late morning) and Friday the 21st of August NZST a Mapbox API change caused our iOS app to crash on start up when retrieving directions. This was caused by forcibly unwrapping a nil optional in RoadClasses.swift (line 102).

The change to the API was subsequently rolled back, but it bricked our production app for over a day.

Changes

  • Use an optional binding to throw a DirectionsError which can be handled by the caller, instead of causing a fatal error.

Crash Report

Retrieved from Crashlytics:

Crashed: com.apple.root.user-initiated-qos
EXC_BREAKPOINT 0x0000000105b104a8

Crashed: com.apple.root.user-initiated-qos
0  MapboxDirections               0x105b104a8 $s16MapboxDirections11RoadClassesV4fromACs7Decoder_p_tKcfCTf4nd_n + 276
1  MapboxDirections               0x105b100bc $s16MapboxDirections11RoadClassesVSeAASe4fromxs7Decoder_p_tKcfCTW + 20
2  libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
3  libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
4  libswiftFoundation.dylib       0x1bc6c7d4c _JSONKeyedDecodingContainer.decode<A>(_:forKey:) + 560
5  libswiftFoundation.dylib       0x1bc7139d0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 36
6  libswiftFoundation.dylib       0x1bc6c9ff0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 20
7  libswiftCore.dylib             0x19336374c KeyedDecodingContainerProtocol.decodeIfPresent<A>(_:forKey:) + 208
8  libswiftFoundation.dylib       0x1bc6ca23c protocol witness for KeyedDecodingContainerProtocol.decodeIfPresent<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 32
9  libswiftCore.dylib             0x193369f3c _KeyedDecodingContainerBox.decodeIfPresent<A>(_:forKey:) + 40
10 libswiftCore.dylib             0x193363d50 KeyedDecodingContainer.decodeIfPresent<A>(_:forKey:) + 40
11 MapboxDirections               0x105aff738 $s16MapboxDirections12IntersectionV4fromACs7Decoder_p_tKcfC + 1924
12 MapboxDirections               0x105affb90 $s16MapboxDirections12IntersectionVSeAASe4fromxs7Decoder_p_tKcfCTW + 12
13 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
14 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
15 libswiftFoundation.dylib       0x1bc6ca8cc _JSONUnkeyedDecodingContainer.decode<A>(_:) + 756
16 libswiftFoundation.dylib       0x1bc6cce94 protocol witness for UnkeyedDecodingContainer.decode<A>(_:) in conformance _JSONUnkeyedDecodingContainer + 12
17 libswiftCore.dylib             0x1933717b0 Array<A>.init(from:) + 384
18 libswiftCore.dylib             0x193371f10 protocol witness for Decodable.init(from:) in conformance <A> [A] + 28
19 libswiftCore.dylib             0x19337197c protocol witness for Decodable.init(from:) in conformance <A> [A] + 20
20 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
21 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
22 libswiftFoundation.dylib       0x1bc6c7d4c _JSONKeyedDecodingContainer.decode<A>(_:forKey:) + 560
23 libswiftFoundation.dylib       0x1bc7139d0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 36
24 libswiftFoundation.dylib       0x1bc6c9ff0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 20
25 libswiftCore.dylib             0x19336374c KeyedDecodingContainerProtocol.decodeIfPresent<A>(_:forKey:) + 208
26 libswiftFoundation.dylib       0x1bc6ca23c protocol witness for KeyedDecodingContainerProtocol.decodeIfPresent<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 32
27 libswiftCore.dylib             0x193369f3c _KeyedDecodingContainerBox.decodeIfPresent<A>(_:forKey:) + 40
28 libswiftCore.dylib             0x193363d50 KeyedDecodingContainer.decodeIfPresent<A>(_:forKey:) + 40
29 MapboxDirections               0x105b26a44 $s16MapboxDirections9RouteStepC4fromACs7Decoder_p_tKcfc + 2904
30 MapboxDirections               0x105b25edc $s16MapboxDirections9RouteStepC4fromACs7Decoder_p_tKcfC + 56
31 MapboxDirections               0x105b2772c $s16MapboxDirections9RouteStepCSeAASe4fromxs7Decoder_p_tKcfCTW + 24
32 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
33 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
34 libswiftFoundation.dylib       0x1bc6ca8cc _JSONUnkeyedDecodingContainer.decode<A>(_:) + 756
35 libswiftFoundation.dylib       0x1bc6cce94 protocol witness for UnkeyedDecodingContainer.decode<A>(_:) in conformance _JSONUnkeyedDecodingContainer + 12
36 libswiftCore.dylib             0x1933717b0 Array<A>.init(from:) + 384
37 libswiftCore.dylib             0x193371f10 protocol witness for Decodable.init(from:) in conformance <A> [A] + 28
38 libswiftCore.dylib             0x19337197c protocol witness for Decodable.init(from:) in conformance <A> [A] + 20
39 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
40 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
41 libswiftFoundation.dylib       0x1bc6c7d4c _JSONKeyedDecodingContainer.decode<A>(_:forKey:) + 560
42 libswiftFoundation.dylib       0x1bc7139d0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 36
43 libswiftFoundation.dylib       0x1bc6c9ff0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 20
44 libswiftCore.dylib             0x193369bd0 _KeyedDecodingContainerBox.decode<A>(_:forKey:) + 40
45 libswiftCore.dylib             0x19331edbc KeyedDecodingContainer.decode<A>(_:forKey:) + 40
46 MapboxDirections               0x105b12b6c $s16MapboxDirections8RouteLegC4fromACs7Decoder_p_tKcfc + 1412
47 MapboxDirections               0x105b125d8 $s16MapboxDirections8RouteLegC4fromACs7Decoder_p_tKcfC + 56
48 MapboxDirections               0x105b14f2c $s16MapboxDirections8RouteLegCSeAASe4fromxs7Decoder_p_tKcfCTW + 24
49 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
50 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
51 libswiftFoundation.dylib       0x1bc6ca8cc _JSONUnkeyedDecodingContainer.decode<A>(_:) + 756
52 libswiftFoundation.dylib       0x1bc6cce94 protocol witness for UnkeyedDecodingContainer.decode<A>(_:) in conformance _JSONUnkeyedDecodingContainer + 12
53 libswiftCore.dylib             0x1933717b0 Array<A>.init(from:) + 384
54 libswiftCore.dylib             0x193371f10 protocol witness for Decodable.init(from:) in conformance <A> [A] + 28
55 libswiftCore.dylib             0x19337197c protocol witness for Decodable.init(from:) in conformance <A> [A] + 20
56 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
57 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
58 libswiftFoundation.dylib       0x1bc6c7d4c _JSONKeyedDecodingContainer.decode<A>(_:forKey:) + 560
59 libswiftFoundation.dylib       0x1bc7139d0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 36
60 libswiftFoundation.dylib       0x1bc6c9ff0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 20
61 libswiftCore.dylib             0x193369bd0 _KeyedDecodingContainerBox.decode<A>(_:forKey:) + 40
62 libswiftCore.dylib             0x19331edbc KeyedDecodingContainer.decode<A>(_:forKey:) + 40
63 MapboxDirections               0x105af8ef0 $s16MapboxDirections0B6ResultC4fromACs7Decoder_p_tKcfc + 908
64 MapboxDirections               0x105b10800 $s16MapboxDirections5RouteC4fromACs7Decoder_p_tKcfC + 56
65 MapboxDirections               0x105afa730 $s16MapboxDirections0B6ResultCSeAASe4fromxs7Decoder_p_tKcfCTW + 24
66 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
67 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
68 libswiftFoundation.dylib       0x1bc6ca8cc _JSONUnkeyedDecodingContainer.decode<A>(_:) + 756
69 libswiftFoundation.dylib       0x1bc6cce94 protocol witness for UnkeyedDecodingContainer.decode<A>(_:) in conformance _JSONUnkeyedDecodingContainer + 12
70 libswiftCore.dylib             0x1933717b0 Array<A>.init(from:) + 384
71 libswiftCore.dylib             0x193371f10 protocol witness for Decodable.init(from:) in conformance <A> [A] + 28
72 libswiftCore.dylib             0x19337197c protocol witness for Decodable.init(from:) in conformance <A> [A] + 20
73 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
74 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
75 libswiftFoundation.dylib       0x1bc6c7d4c _JSONKeyedDecodingContainer.decode<A>(_:forKey:) + 560
76 libswiftFoundation.dylib       0x1bc7139d0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 36
77 libswiftFoundation.dylib       0x1bc6c9ff0 protocol witness for KeyedDecodingContainerProtocol.decode<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 20
78 libswiftCore.dylib             0x19336374c KeyedDecodingContainerProtocol.decodeIfPresent<A>(_:forKey:) + 208
79 libswiftFoundation.dylib       0x1bc6ca23c protocol witness for KeyedDecodingContainerProtocol.decodeIfPresent<A>(_:forKey:) in conformance _JSONKeyedDecodingContainer<A> + 32
80 libswiftCore.dylib             0x193369f3c _KeyedDecodingContainerBox.decodeIfPresent<A>(_:forKey:) + 40
81 libswiftCore.dylib             0x193363d50 KeyedDecodingContainer.decodeIfPresent<A>(_:forKey:) + 40
82 MapboxDirections               0x105b1cabc $s16MapboxDirections13RouteResponseV4fromACs7Decoder_p_tKcfC + 2932
83 MapboxDirections               0x105b1d9d4 $s16MapboxDirections13RouteResponseVSeAASe4fromxs7Decoder_p_tKcfCTW + 12
84 libswiftCore.dylib             0x19343d914 dispatch thunk of Decodable.init(from:) + 16
85 libswiftFoundation.dylib       0x1bc6d2f8c __JSONDecoder.unbox_(_:as:) + 3276
86 libswiftFoundation.dylib       0x1bc6bdab0 JSONDecoder.decode<A>(_:from:) + 888
87 libswiftFoundation.dylib       0x1bc786680 dispatch thunk of JSONDecoder.decode<A>(_:from:) + 20
88 MapboxDirections               0x105ae2f9c $s16MapboxDirections0B0C9calculate_17completionHandlerSo20NSURLSessionDataTaskCAA12RouteOptionsC_yAA0bJ0C7options_AA0B11CredentialsV11credentialst_s6ResultOyAA0I8ResponseVAA0B5ErrorOGtctFy10Foundation0G0VSg_So13NSURLResponseCSgs0P0_pSgtcfU_yycfU2_ + 1400
89 MapboxDirections               0x105aea1d4 $s16MapboxDirections0B0C15calculateRoutes8matching17completionHandlerSo20NSURLSessionDataTaskCAA12MatchOptionsC_yAA0bL0C7options_AA0B11CredentialsV11credentialst_s6ResultOyAA13RouteResponseVAA0B5ErrorOGtctFy10Foundation0I0VSg_So13NSURLResponseCSgs0S0_pSgtcfU_yycfU2_TATm + 44
90 MapboxDirections               0x105ae2a14 $sIeg_IeyB_TR + 28
91 libdispatch.dylib              0x1859aa9a8 _dispatch_call_block_and_release + 24
92 libdispatch.dylib              0x1859ab524 _dispatch_client_callout + 16
93 libdispatch.dylib              0x18599165c _dispatch_root_queue_drain + 640
94 libdispatch.dylib              0x185991cd0 _dispatch_worker_thread2 + 112
95 libsystem_pthread.dylib        0x1859fcb38 _pthread_wqthread + 212
96 libsystem_pthread.dylib        0x1859ff740 start_wqthread + 8

Copy link
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I agree that we need additional safety on the client-side here.

@1ec5 1ec5 merged commit 8fe8ce1 into mapbox:release-v0.31 Sep 2, 2020
@1ec5 1ec5 linked an issue Sep 2, 2020 that may be closed by this pull request
@1ec5 1ec5 linked an issue Sep 2, 2020 that may be closed by this pull request
@1ec5
Copy link
Contributor

1ec5 commented Sep 2, 2020

Cherry-picked to the master and main branches in 4d7ea73.

@1ec5
Copy link
Contributor

1ec5 commented Sep 2, 2020

Added to the changelog in 0c97fed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Crash when decoding unexpected road class
2 participants