mapbox-maps-ios icon indicating copy to clipboard operation
mapbox-maps-ios copied to clipboard

Crash - Duplicate keys of type 'AnyHashable' were found in a Dictionary.

Open thomas-hensel opened this issue 11 months ago • 3 comments

Environment

  • Xcode version: Version 16.2 (16C5032a)
  • iOS version: iOS 18.2.1 (22C161)
  • Devices affected: all
  • Maps SDK Version: 11.9.0 (and possibly 11.8.0)

Observed behavior and steps to reproduce

Crash with: ' were found in a Dictionary. This usually means either that the type violates Hashable's requirements, or that members of such a dictionary were mutated after insertion. > Fatal error

Happens randomly during View update, various devices, could not yet be observed in debug Affects stability of the app

Expected behavior

No crash

Notes / preliminary analysis

in final class AnnotationManagerImpl<AnnotationType: Annotation & AnnotationInternal & Equatable>: AnnotationManagerImplProtocol {

func set(newAnnotations: [(AnyHashable, AnnotationType)]) {
    var resolvedAnnotations = [AnnotationType]()
    newAnnotations.forEach { elementId, annotation in
        var annotation = annotation
        let stringId = idsMap[elementId] ?? annotation.id
        idsMap[elementId] = stringId

Duplicate keys of type 'AnyHashable' were found in a Dictionary. This usually means either that the type violates Hashable's requirements, or that members of such a dictionary were mutated after insertion. po idsMap shows: Simultaneous accesses to 0x158d4cfd0, but modification requires exclusive access. Previous access (a modification) started at closure #1 in AnnotationManagerImpl.set(newAnnotations:) + 3120 (0x10b108460).

        annotation.id = stringId
        annotation.isDraggable = false
        annotation.isSelected = false
        resolvedAnnotations.append(annotation)
    }
    // TODO: evict old ids
    annotations = resolvedAnnotations
}

Sentry Thread Stack Trace

ibswiftCore +0x01172c
_assertionFailure(_: StaticString, _: String, flags: UInt32
libswiftCore +0x198624
KEY_TYPE_OF_DICTIONARY_VIOLATES_HASHABLE_REQUIREMENTS(Any.Type)
+0x60ac70
specialized _NativeDictionary.mutatingFind(_: A, isUnique: Bool) (<compiler-generated>)
+0x2dd60c
specialized _NativeDictionary.setValue(_: __owned B, forKey: A, isUnique: Bool) (<compiler-generated>)
+0x2dd60c
specialized Dictionary._Variant.setValue(_: __owned B, forKey: A) (<compiler-generated>)
+0x2c78f4
specialized Dictionary.subscript.setter (<compiler-generated>)
+0x2c78f4
**closure #1 (AnyHashable, A) in AnnotationManagerImpl.set(newAnnotations: [(AnyHashable, A)]) (AnnotationManagerImpl.swift:211)**
+0x2caa74
thunk for @callee_guaranteed (@in_guaranteed AnyHashable, @in_guaranteed A) -> () (<compiler-generated>)
libswiftCore +0x0f4c9c
Sequence.forEach((A.Element))
+0x2c779c
**AnnotationManagerImpl.set(newAnnotations: [(AnyHashable, A)]) (AnnotationManagerImpl.swift:208)**
+0x346c68
MountedAnnotationGroup.update(manager: A, context: MapContentNodeContext) (MountedAnnotationGroup.swift:61)
+0x347048
MountedAnnotationGroup.tryUpdate(from: MapContentMountedComponent, with: MapContentNodeContext) (MountedAnnotationGroup.swift:52)
+0x3471bc
protocol witness for MapContentMountedComponent.tryUpdate(from: MapContentMountedComponent, with: MapContentNodeContext) in conformance MountedAnnotationGroup<A> (<compiler-generated>)
+0x359928
MapContentNode.update<A>(with: A) (MapContentNode.swift:97)
+0x330c50
MapContent.update(MapContentNode) (MapContent.swift:93)
+0x330ac0
$s10MapboxMaps15TupleMapContentVyACyqd__qd__Qp_tGqd__qd__QpcRvd__qd__qd__Qp_tRszAA0dE0Rd__lufcyAA0dE4NodeCcfU_yAGyXEXEfU_ (MapContent.swift:24)
+0x3308d8
MapContentNode.withChildrenNodes((())) (MapContentNode.swift:42)
+0x3308d8
$s10MapboxMaps15TupleMapContentVyACyqd__qd__Qp_tGqd__qd__QpcRvd__qd__qd__Qp_tRszAA0dE0Rd__lufcyAA0dE4NodeCcfU_ (MapContent.swift:23)
+0x1f067c
specialized thunk for @escaping @callee_guaranteed (@in_guaranteed A) -> () (<compiler-generated>)
+0x359850
MapContentNode.update<A>(with: A) (MapContentNode.swift:82)
+0x330c50
MapContent.update(MapContentNode) (MapContent.swift:93)
+0x3312d8
closure #1 (()) in OptionalMapContent.visit(MapContentNode) (MapContent.swift:79)
+0x331190
MapContentNode.withChildrenNodes((())) (MapContentNode.swift:42)
+0x331190
OptionalMapContent.visit(MapContentNode) (MapContent.swift:77)
+0x359850
MapContentNode.update<A>(with: A) (MapContentNode.swift:82)
+0x330c50
MapContent.update(MapContentNode) (MapContent.swift:93)
+0x330ac0
$s10MapboxMaps15TupleMapContentVyACyqd__qd__Qp_tGqd__qd__QpcRvd__qd__qd__Qp_tRszAA0dE0Rd__lufcyAA0dE4NodeCcfU_yAGyXEXEfU_ (MapContent.swift:24)
+0x3308d8
MapContentNode.withChildrenNodes((())) (MapContentNode.swift:42)
+0x3308d8
$s10MapboxMaps15TupleMapContentVyACyqd__qd__Qp_tGqd__qd__QpcRvd__qd__qd__Qp_tRszAA0dE0Rd__lufcyAA0dE4NodeCcfU_ (MapContent.swift:23)
+0x1f067c
specialized thunk for @escaping @callee_guaranteed (@in_guaranteed A) -> () (<compiler-generated>)
+0x359850
MapContentNode.update<A>(with: A) (MapContentNode.swift:82)
+0x330c50
MapContent.update(MapContentNode) (MapContent.swift:93)
+0x35d26c
MapContentNodeContext.update(mapContent: MapContent, root: MapContentNode) (MapContentReconciler.swift:75)
+0x35ca48
MapContentReconciler.update(with: MapContent) (MapContentReconciler.swift:47)
+0x64aa68
MapContentReconciler.content.didset (MapContentReconciler.swift:8)
+0x64aa68
MapContentReconciler.content.setter (MapContentReconciler.swift)
+0x64aa68
StyleManager.setMapContent(()) (StyleManager.swift:461)
+0x68de68
MapBasicCoordinator.update(viewport: ConstantOrBinding<Viewport>, deps: MapDependencies, layoutDirection: LayoutDirection, animationData: ViewportAnimationData?) (MapBasicCoordinator.swift:91)
+0x689044
Map.updateUIViewController(_: UIViewController, context: UIViewControllerRepresentableContext<Map>) (Map.swift:143)

Additional links and references

thomas-hensel avatar Jan 18 '25 13:01 thomas-hensel

Thank you @thomas-hensel for reporting this, I have created an internal issue to track the progress of this https://mapbox.atlassian.net/browse/MAPSIOS-1713

maios avatar Jan 22 '25 08:01 maios

@thomas-hensel Hi, do you have any scenario to reproduce it?

persidskiy avatar Apr 29 '25 16:04 persidskiy

As I needed a quick solution I rewrote my code segment, that gave these crashes.

From what I remember, it was like this:

CircleAnnotationGroup(locations, id: \.self) { location in
 CircleAnnotation(centerCoordinate: CLLocationCoordinate2DMake(location.latitude, location.longitude) , isDraggable: true)
}

locations is a SwiftData object collection. It has crashed very randomly once a day and I could not see a pattern, unfortunately.

I rewrote it to

ForEvery(locations) { location in
       CircleAnnotation(centerCoordinate: CLLocationCoordinate2DMake(location.latitude, location.longitude) , isDraggable: false)
}

and the error did not pop up since then.

thomas-hensel avatar Apr 29 '25 16:04 thomas-hensel