Skip to content

Add NO_DIRECT_MODE_CONNECTION routing error code for direct-only searches#7494

Open
vpaturet wants to merge 2 commits intoopentripplanner:dev-2.xfrom
entur:add-no-direct-mode-connection-error-code
Open

Add NO_DIRECT_MODE_CONNECTION routing error code for direct-only searches#7494
vpaturet wants to merge 2 commits intoopentripplanner:dev-2.xfrom
entur:add-no-direct-mode-connection-error-code

Conversation

@vpaturet
Copy link
Copy Markdown
Contributor

@vpaturet vpaturet commented Apr 1, 2026

Summary

Add a new NO_DIRECT_MODE_CONNECTION routing error code returned when a direct-only search
(no transit modes requested) yields no itineraries. This gives API consumers a clear reason
code for empty results and eliminates ~97% of the "routing result is empty but there is no
errors" warnings in production.

Issue

Production logs show ~876 "empty routing result" warnings per minute (87.6% of all warnings).
96.7% are direct-only searches
(transportModes: []) — clients fan out
parallel direct-mode requests (flex, foot, bicycle, car, bike_rental, scooter_rental) alongside
transit queries. When a direct mode can't find a route, the result is empty with no error code.

The root cause: direct routing methods (routeDirectStreet, routeDirectFlex,
routeDirectCarpooling) return RoutingResult.ok(List.of()) when they find nothing — no error
is ever attached. The RoutingErrorsAttacher only handles transit-related errors. For direct-only
searches, transit is disabled, so no error codes apply.

Example query:

{                                                                                                                                                                                                                                                                                                                                                                                                                 
    trip(                                                                                                                                                                                                                                                                                                                                                                                                           
      from: { coordinates: { latitude: 59.911, longitude: 10.753 } }                                                                                                                                                                                                                                                                                                                                                
      to: { coordinates: { latitude: 60.393, longitude: 5.324 } }                                                                                                                                                                                                                                                                                                                                                   
      modes: {                                              
        directMode: bicycle                                                                                                                                                                                                                                                                                                                                                                                         
        transportModes: []                                  
      }                                                                                                                                                                                                                                                                                                                                                                                                             
    ) {                                                     
      routingErrors {
        code
        description
        inputField
      }
      tripPatterns {
        duration                                                                                                                                                                                                                                                                                                                                                                                                    
        legs {
          mode                                                                                                                                                                                                                                                                                                                                                                                                      
        }                                                   
      }
    }
  }

returns currently:

{
  "data": {
    "trip": {
      "routingErrors": [],
      "tripPatterns": []
    }
  }
}

and with the fix:

{
  "data": {
    "trip": {
      "routingErrors": [
        {
          "code": "noDirectModeConnection",
          "description": "No route found for the requested direct mode. The origin and destination may be too far apart or not connected by the requested mode of transport.",
          "inputField": null
        }
      ],
      "tripPatterns": []
    }
  }
}

How it works

A new checkForEmptyDirectModeResult() method in RoutingWorker checks after the filter chain
whether:

  • Transit was not requested (!request.journey().transit().enabled())
  • No other error was already set (e.g. OUTSIDE_BOUNDS)
  • All itineraries are empty or flagged for deletion

If all three are true, the new NO_DIRECT_MODE_CONNECTION error is attached. This naturally
silences the warning in DefaultRoutingService.logResponse() since getRoutingErrors() is no
longer empty.

The error code is exposed in both the TransModel (noDirectModeConnection) and GTFS
(NO_DIRECT_MODE_CONNECTION) GraphQL schemas.

Unit tests

  • EnumTypesTest#assertAllRoutingErrorCodesAreMapped validates the new code is mapped
  • GraphQLUtilsTest validates the GTFS enum mapping
  • TransmodelGraphQLSchemaTest#testSchemaBuild validates schema integrity

Documentation

  • Javadoc on the new enum value and method
  • GraphQL schema descriptions for both TransModel and GTFS APIs

@vpaturet vpaturet changed the title Add NO_DIRECT_MODE_CONNECTION routing error code for direct-only sear… Add NO_DIRECT_MODE_CONNECTION routing error code for direct-only searches Apr 1, 2026
@vpaturet vpaturet force-pushed the add-no-direct-mode-connection-error-code branch from 62848e1 to 934887b Compare April 1, 2026 10:31
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 1, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.02%. Comparing base (f4370ca) to head (578e686).
⚠️ Report is 18 commits behind head on dev-2.x.

Files with missing lines Patch % Lines
...entripplanner/routing/algorithm/RoutingWorker.java 57.14% 1 Missing and 2 partials ⚠️
...anner/apis/support/mapping/PlannerErrorMapper.java 0.00% 2 Missing ⚠️
...va/org/opentripplanner/apis/gtfs/GraphQLUtils.java 0.00% 1 Missing ⚠️
...ntripplanner/apis/gtfs/generated/GraphQLTypes.java 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             dev-2.x    #7494   +/-   ##
==========================================
  Coverage      71.02%   71.02%           
- Complexity     20995    21009   +14     
==========================================
  Files           2348     2352    +4     
  Lines          87252    87280   +28     
  Branches        8640     8638    -2     
==========================================
+ Hits           61968    61994   +26     
- Misses         22291    22298    +7     
+ Partials        2993     2988    -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…ches

When a direct-only search (no transit modes requested) returns no
itineraries, attach a new NO_DIRECT_MODE_CONNECTION error code so
clients can distinguish "no direct route found" from "something went
wrong." This eliminates ~97% of the "routing result is empty but there
is no errors" warnings in production, which are caused by clients
fanning out parallel direct-mode requests (flex, foot, bicycle, car,
etc.) alongside transit queries.
@vpaturet vpaturet force-pushed the add-no-direct-mode-connection-error-code branch from 934887b to c23e7c5 Compare April 7, 2026 08:33
@vpaturet vpaturet marked this pull request as ready for review April 7, 2026 08:43
@vpaturet vpaturet requested a review from a team as a code owner April 7, 2026 08:43
@optionsome optionsome requested review from optionsome and t2gran April 7, 2026 09:02
@optionsome optionsome added the !Improvement A functional improvement or micro feature label Apr 7, 2026
@vpaturet vpaturet added Entur Test This is currently being tested at Entur labels Apr 7, 2026
@vpaturet vpaturet marked this pull request as draft April 7, 2026 17:21
@vpaturet
Copy link
Copy Markdown
Contributor Author

vpaturet commented Apr 7, 2026

Moving temporarily to draft, it seems the error message mapping is incorrect.

@vpaturet
Copy link
Copy Markdown
Contributor Author

vpaturet commented Apr 8, 2026

Added a dedicated error message for no direct mode conection

@vpaturet vpaturet marked this pull request as ready for review April 8, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Entur Test This is currently being tested at Entur !Improvement A functional improvement or micro feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants