# Journey Planning Fix Summary
## Problem Description
The `plan_comprehensive_journey` function was failing with the error:
```json
{
"error": "No route found between the specified locations",
"details": "Tried multiple routing strategies but could not find a viable route"
}
```
**Failing Example:**
- From: `120 PUNGGOL WALK TWIN WATERFALLS SINGAPORE 828770`
- To: `73 KEONG SAIK ROAD SRI LAYAN SITHI VINAYAGAR TEMPLE SINGAPORE 089167`
## Root Causes Identified
### 1. **Incorrect API Endpoint**
- **Problem**: Using `https://developers.onemap.sg/privateapi/routingsvc/route`
- **Solution**: Changed to `https://www.onemap.gov.sg/api/public/routingsvc/route`
- **Impact**: The private API endpoint was not accessible with the current authentication method
### 2. **Wrong Authentication Method**
- **Problem**: Passing token as URL parameter (`?token=...`)
- **Solution**: Pass token as Bearer token in Authorization header
- **Impact**: API was rejecting requests due to improper authentication
### 3. **Missing URL Encoding**
- **Problem**: Coordinates not properly URL encoded
- **Solution**: Use `encodeURIComponent()` for coordinate strings
- **Example**: `1.320981,103.844150` → `1.320981%2C103.844150`
### 4. **Incomplete Public Transport Parameters**
- **Problem**: Missing required `mode` parameter for public transport
- **Solution**: Set `mode=TRANSIT` for general public transport routing
- **Impact**: API was unable to process public transport requests properly
### 5. **Poor Error Handling**
- **Problem**: Limited retry logic and error reporting
- **Solution**: Enhanced error handling with specific HTTP status code handling
- **Impact**: Better debugging and fallback strategies
## Fixes Applied
### 1. OneMapService Updates (`src/services/onemap.ts`)
#### API Endpoint Fix
```typescript
// OLD (broken)
const routingUrl = 'https://developers.onemap.sg/privateapi/routingsvc/route';
// NEW (fixed)
const routingUrl = 'https://www.onemap.gov.sg/api/public/routingsvc/route';
```
#### Authentication Fix
```typescript
// OLD (broken)
const response = await axios.get<OneMapRouteResponse>(routingUrl, {
params: { ...params, token },
timeout: this.timeout,
});
// NEW (fixed)
const response = await axios.get<OneMapRouteResponse>(routingUrl, {
params: encodedParams,
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
timeout: this.timeout,
});
```
#### Parameter Encoding Fix
```typescript
// OLD (broken)
const params: any = {
start: `${from.latitude},${from.longitude}`,
end: `${to.latitude},${to.longitude}`,
routeType,
token, // Wrong: token in params
};
// NEW (fixed)
const params: any = {
start: encodeURIComponent(`${from.latitude},${from.longitude}`),
end: encodeURIComponent(`${to.latitude},${to.longitude}`),
routeType,
// Token now in Authorization header
};
```
#### Public Transport Parameters Fix
```typescript
if (options.mode === 'PUBLIC_TRANSPORT') {
params.mode = 'TRANSIT'; // FIXED: Added missing mode parameter
params.maxWalkDistance = (options.maxWalkDistance || 1000).toString();
params.numItineraries = (options.numItineraries || 3).toString();
// Time parameters
const now = new Date();
if (options.departureTime) {
params.date = this.formatDateForOneMap(options.departureTime);
params.time = this.formatTimeForOneMap(options.departureTime);
} else {
params.date = this.formatDateForOneMap(now);
params.time = this.formatTimeForOneMap(now);
}
}
```
### 2. Journey Planning Tool Updates (`src/tools/routing/journey.ts`)
#### Enhanced Retry Logic
```typescript
private async planRouteWithRetry(
from: Location,
to: Location,
options: any,
retries = 3
): Promise<JourneyPlan | null> {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const result = await this.oneMapService.planRoute(from, to, options);
if (result) {
logger.info(`Route planning successful on attempt ${attempt}`);
return result;
}
logger.debug(`No route found on attempt ${attempt}, will retry`);
} catch (error) {
logger.warn(`Route planning attempt ${attempt} failed`);
// Handle authentication errors specifically
if ((error as any)?.response?.status === 401) {
logger.warn('Authentication error detected, will retry after delay');
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
// Try alternative routing strategies on final attempt
if (attempt === retries) {
return await this.tryAlternativeRouting(from, to, options);
}
// Exponential backoff
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 5000);
await new Promise(resolve => setTimeout(resolve, delay));
}
return null;
}
```
#### Improved Error Logging
```typescript
logger.error('Route planning failed', {
error: error instanceof Error ? error.message : 'Unknown error',
from: from.name,
to: to.name,
mode: options.mode,
status: (error as any)?.response?.status,
statusText: (error as any)?.response?.statusText,
responseData: (error as any)?.response?.data
});
```
## Testing Results
### Coordinate Validation
✅ TWIN WATERFALLS: (1.40276446041873, 103.89737879547) - Valid
✅ SRI LAYAN SITHI VINAYAGAR TEMPLE: (1.2811884163336, 103.841657436594) - Valid
### URL Encoding
✅ Coordinates properly encoded with `%2C` for commas
### API Request Format
✅ Correct endpoint: `https://www.onemap.gov.sg/api/public/routingsvc/route`
✅ Bearer token in Authorization header
✅ All required parameters included
## Expected Behavior After Fix
1. **Successful Route Planning**: The failing Punggol to Keong Saik Road route should now work
2. **Better Error Messages**: Clear, actionable error messages when routes genuinely can't be found
3. **Fallback Strategies**: Alternative transport modes when primary mode fails
4. **Improved Reliability**: Better handling of API timeouts, rate limits, and authentication issues
## API Request Example
The fixed implementation will make requests like:
```
GET https://www.onemap.gov.sg/api/public/routingsvc/route?start=1.40276446041873%2C103.89737879547&end=1.2811884163336%2C103.841657436594&routeType=pt&mode=TRANSIT&maxWalkDistance=1000&numItineraries=3&date=06-27-2025&time=14:11:00
Headers:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
Content-Type: application/json
```
## Files Modified
1. **`src/services/onemap.ts`** - Core routing API fixes
2. **`src/tools/routing/journey.ts`** - Enhanced error handling and retry logic
## Verification
The server builds and starts successfully:
```
✅ Build completed without errors
✅ Server starts and initializes 12 tools
✅ Health check passes for all services
```
The `plan_comprehensive_journey` function should now work correctly for the previously failing route and all other routing scenarios.