Get multiple unassigned job reasons
By default, when the HERE Tour Planning API cannot assign a job to any vehicle, it returns a single reason code that identifies the most frequent constraint violation across all vehicles in the fleet. However, a job might fail to be assigned for different reasons across different vehicles, making it more challenging to diagnose the root cause when only one reason is provided.
Understand single vs. multiple unassigned reasons
By default, the unassigned job response contains only a single reason—typically the most frequent constraint violation across all vehicles. For example:
{
"jobId": "9e76e576-5038-4f55-9b6a-4ac9fbfd440b",
"reasons": [
{
"code": "TERRITORY_CONSTRAINT",
"description": "cannot be assigned due to territory constraint"
}
]
}With the multipleUnassignedReasons experimental feature enabled, you receive multiple applicable reason codes for each unassigned job, grouped by vehicle shift, for example:
{
"jobId": "9e76e576-5038-4f55-9b6a-4ac9fbfd440b",
"reasons": [
{
"code": "TERRITORY_CONSTRAINT",
"description": "cannot be assigned due to territory constraint",
"details": [
{
"shiftIndex": 0,
"vehicleIds": [
"218_1_1",
"655_1_1",
"695_1_1",
"712_1_1"
]
}
]
},
{
"code": "TIME_WINDOW_CONSTRAINT",
"description": "cannot be assigned due to violation of time window",
"details": [
{
"shiftIndex": 0,
"vehicleIds": [
"166_1_1",
"180_1_1",
"217_1_1"
]
}
]
}
]
}Note
The same vehicle can appear in multiple reason codes if it has multiple shifts and the job fails different constraints in different shifts, for example:
{ "jobId": "9e76e576-5038-4f55-9b6a-4ac9fbfd440b", "reasons": [ { "code": "CAPACITY_CONSTRAINT", "description": "cannot be assigned due to capacity of vehicle", "details": [ { "shiftIndex": 0, "vehicleIds": [ "218_1_1" ] } ] }, { "code": "TIME_WINDOW_CONSTRAINT", "description": "cannot be assigned due to violation of time window", "details": [ { "shiftIndex": 1, "vehicleIds": [ "218_1_1" ] } ] } ] }
This feature provides a comprehensive view of why a job could not be assigned, enabling you to make more informed decisions when adjusting your problem definition.
Enable multiple unassigned reasons
Note
This is an ALPHA feature, which means it is new or experimental and under active development. Alpha features are provided for testing and feedback purposes. They may change significantly or might not become generally available.
For more information, see Explore experimental features.
To receive multiple unassigned reasons in your solution, add the multipleUnassignedReasons feature to the experimentalFeatures array in your problem configuration:
{
"configuration": {
"experimentalFeatures": [
"multipleUnassignedReasons"
]
},
"fleet": {
...
},
"plan": {
...
}
}When the multipleUnassignedReasons feature is enabled, the solution includes a reasons array for each unassigned job. Unlike the default behavior which returns only a single reason, this array can contain multiple reason codes for the same job, allowing you to see all the different constraint violations across your fleet. Each reason contains:
code: The constraint violation reason code (for example,SKILL_CONSTRAINT,CAPACITY_CONSTRAINT)description: A human-readable explanation of the constraint violationdetails: An array of objects specifying which vehicles and shifts are affected by this particular constraint
Important
Multiple unassigned reasons are only reported based on vehicles that are actually used in the solution.
For an unassigned job, the service checks all created tours and aggregates reasons why the job could not be added to any of those tours. Vehicles for which no tour was created are ignored. Consider a problem that includes
Vehicle_1andVehicle_2as the available vehicle fleet:
- If only one vehicle is used in the solution, you see only the constraint associated with that vehicle (for example,
CAPACITY_CONSTRAINTorSKILL_CONSTRAINT).- Multiple unassigned reasons (for example, both
CAPACITY_CONSTRAINTandSKILL_CONSTRAINT, orCAPACITY_CONSTRAINTandREACHABLE_CONSTRAINT) are only shown when tours exist for multiple vehicles that were considered for the job.
Example: Diagnose complex constraint violations
This example demonstrates how multiple unassigned reasons help diagnose why a job cannot be assigned when different vehicles fail for different reasons.
Problem overview
The fleet consists of:
- One car (
car_1): Has 4-unit capacity, has thebulky_itemsskill for transporting large packages - Two scooters (
scooter_1): Each has 2-unit capacity, has theexpress_deliveryskill for time-sensitive deliveries
The jobs are distributed as follows:
- Jobs 1-3: Require the
bulky_itemsskill (1 unit each) - Jobs 4-8: Require the
express_deliveryskill (1 unit each)
The tight capacity and skill constraints create a scenario where Job_8 cannot be assigned to any vehicle.
Problem
The following section contains the complete problem JSON that demonstrates multiple unassigned reasons:
Click to expand/collapse the sample JSON
{ "configuration": {
"experimentalFeatures": [
"multipleUnassignedReasons"
]
},
"fleet": {
"types": [
{
"id": "car_1",
"profile": "car",
"costs": {
"fixed": 10.0,
"distance": 0.001,
"time": 0.002
},
"shifts": [
{
"start": {
"time": "2024-06-24T06:00:00Z",
"location": {
"lat": 52.53097,
"lng": 13.38504
}
},
"end": {
"time": "2024-06-24T06:45:00Z",
"location": {
"lat": 52.53097,
"lng": 13.38504
}
}
}
],
"capacity": [4],
"skills": ["bulky_items"],
"amount": 1
},
{
"id": "scooter_1",
"profile": "scooter",
"costs": {
"fixed": 10.0,
"distance": 0.001,
"time": 0.002
},
"shifts": [
{
"start": {
"time": "2024-06-24T06:00:00Z",
"location": {
"lat": 52.53097,
"lng": 13.38504
}
},
"end": {
"time": "2024-06-24T06:45:00Z",
"location": {
"lat": 52.53097,
"lng": 13.38504
}
}
}
],
"capacity": [2],
"skills": ["express_delivery"],
"amount": 2
}
],
"profiles": [
{
"type": "car",
"name": "car"
},
{
"type": "scooter",
"name": "scooter"
}
]
},
"plan": {
"jobs": [
{
"id": "Job_1",
"skills": ["bulky_items"],
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.531757,
"lng": 13.384426
},
"duration": 300
}
],
"demand": [1]
}
]
}
},
{
"id": "Job_2",
"skills": ["bulky_items"],
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.532983,
"lng": 13.38787
},
"duration": 300
}
],
"demand": [1]
}
]
}
},
{
"id": "Job_3",
"skills": ["bulky_items"],
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.532065,
"lng": 13.389091
},
"duration": 300
}
],
"demand": [1]
}
]
}
},
{
"id": "Job_4",
"skills": ["express_delivery"],
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.530384,
"lng": 13.391224
},
"duration": 300
}
],
"demand": [1]
}
]
}
},
{
"id": "Job_5",
"skills": ["express_delivery"],
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.530008,
"lng": 13.389562
},
"duration": 300
}
],
"demand": [1]
}
]
}
},
{
"id": "Job_6",
"skills": ["express_delivery"],
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.529496,
"lng": 13.385547
},
"duration": 300
}
],
"demand": [1]
}
]
}
},
{
"id": "Job_7",
"skills": ["express_delivery"],
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.528909,
"lng": 13.385381
},
"duration": 300
}
],
"demand": [1]
}
]
}
},
{
"id": "Job_8",
"skills": ["express_delivery"],
"tasks": {
"deliveries": [
{
"places": [
{
"location": {
"lat": 52.530533,
"lng": 13.383505
},
"duration": 300
}
],
"demand": [1]
}
]
}
}
]
}
}Solution analysis
When you submit this problem with the multipleUnassignedReasons feature enabled, the optimization algorithm assigns Jobs 1-3 to the car and Jobs 4-7 to the two scooters. However, Job_8 remains unassigned. The solution reveals why this job cannot be assigned to any vehicle:
{
"unassigned": [
{
"jobId": "Job_8",
"reasons": [
{
"code": "CAPACITY_CONSTRAINT",
"description": "cannot be assigned due to capacity of vehicle",
"details": [
{
"shiftIndex": 0,
"vehicleIds": [
"scooter_1_1",
"scooter_1_2"
]
}
]
},
{
"code": "SKILL_CONSTRAINT",
"description": "cannot be assigned due to required skill",
"details": [
{
"shiftIndex": 0,
"vehicleIds": [
"car_1_1"
]
}
]
}
]
}
]
}The response shows that:
- Scooter vehicles (
scooter_1_1andscooter_1_2) cannot takeJob_8due toCAPACITY_CONSTRAINTas both scooters have already reached their 2-unit capacity by serving Jobs 4-7 - Car vehicle (
car_1_1) cannot takeJob_8due toSKILL_CONSTRAINTbecause the car has thebulky_itemsskill, butJob_8requires theexpress_deliveryskill
Comparison with the default behavior
By contrast, if you submit the same problem without the multipleUnassignedReasons feature enabled, the service returns only the most frequent constraint violation:
{
"unassigned": [
{
"jobId": "Job_8",
"reasons": [
{
"code": "CAPACITY_CONSTRAINT",
"description": "cannot be assigned due to capacity of vehicle"
}
]
}
]
}This default response shows only the CAPACITY_CONSTRAINT, which might lead you to believe that extending capacity for a vehicle type is the only solution. However, the complete picture reveals another issue: the car vehicle cannot take this job due to the SKILL_CONSTRAINT. Without the multipleUnassignedReasons feature, you could miss that there are multiple viable paths to resolve this issue.
Resolution strategies
With the complete picture from multiple unassigned reasons, you can choose from a broader range of approaches to resolve the issue, for example:
- Add another scooter to the fleet to handle the remaining
express_deliveryjobs - If operationally feasible, increase the capacity of existing scooters to accommodate more jobs
- Give the car the
express_deliveryskill so it can serveJob_8alongside its other jobs - If
Job_8can be served by any vehicle type, remove or adjust the skill requirement to allow the car to handle it - Allow scooters to unload cargo mid-shift and continue serving additional jobs
The key advantage of multiple unassigned reasons is that you can see more constraint violations at once, giving you more options to choose the solution that is more feasoble, given your business objectives and fleet status. You could resolve the issue by addressing either the capacity constraint on the scooters or the skill constraint on the car.
Next steps
- For common unassigned job reason codes and how to resolve them, see Troubleshoot unassigned jobs.
- For other alpha and beta features available in the HERE Tour Planning API, see Explore experimental features.
- For information about using skills to match jobs with qualified vehicles, see Assign jobs based on skills.
- For information about defining and managing vehicle capacity constraints, see Solve the Capacitated Vehicle Routing Problem (CVRP).
Updated 25 days ago