Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

`MapboxRoutingProvider` crashes when concurrent first route requests initialize `routerClient`

Open
#4,852 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
68/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
swift
Domain
mobile

Research direction

Locate MapboxRoutingProvider and inspect routerClient, calculateRoutes, and doRequest, focusing on how concurrent requests reach the lazy initializer. Verify the fix by exercising concurrent first calls on one provider and confirming that a single RouterClient is initialized without EXC_BAD_ACCESS.

Written by the indexing model from the issue text.

Description

We are seeing an EXC_BAD_ACCESS in Mapbox Navigation iOS 3.26.0 when multiple route requests start concurrently against the same MapboxNavigationProvider / MapboxRoutingProvider.

The crash occurs in MapboxRoutingProvider.routerClient while evaluating its lazy initializer:

private lazy var routerClient: RouterClient = {
    let factory = configuration.nativeHandlersFactory
    let router = RouterFactory.build(
        for: configuration.source.nativeSource,
        tilesManager: factory.tilesManager,
        config: factory.configHandle(),
        historyRecorder: factory.historyRecorderHandle
    )
    return Environment.shared.routerClientProvider.build(router)
}()

We confirmed two concurrent threads entering RouterFactory.build during the first access. This races the lazy initialization and produces:

EXC_BAD_ACCESS
objc_retain
closure #1 in MapboxRoutingProvider.routerClient.getter
MapboxRoutingProvider.routerClient.getter
MapboxRoutingProvider.doRequest(...)
MapboxRoutingProvider.calculateRoutes(...)

Our route-preview UI starts concurrent requests for walking, driving, and cycling. The app safely caches a single MapboxNavigationProvider, but each request calls calculateRoutes independently. MapboxRoutingProvider is declared @unchecked Sendable, creates an unstructured Task per request, and has no actor isolation, lock, or other synchronization around routerClient.

withCheckedContinuation correctly bridges each native callback, but it does not serialize separate calls to doRequest.

Expected behavior: concurrent calls to calculateRoutes on one provider should safely share a single initialized RouterClient.

Current behavior: concurrent first calls can initialize routerClient simultaneously and crash.

Could you please protect routerClient initialization/access with actor isolation or explicit synchronization, rather than relying on an unsynchronized lazy var?

Dominant language
Swift
Stars
919
Forks
328
Avg merge
2d 51m
Merged PRs (30d)
5

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from mapbox/mapbox-navigation-ios

All issues in mapbox/mapbox-navigation-ios

Similar issues

More Swift issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.