Why are my drivers getting "License number must be unique..." errors for some quotes?

Issue

A quote will not be bindable while any driver on the quote has the "License number must be unique..." validation error for its licenseNumber field.

You should expect there to always be at least 2 drivers with this validation error, since all drivers associated with a duplicate license number should be affected.

Example

{
  "quote": {
    "profile": {
      "drivers": [
        {
          "licenseNumber": {
            "value": "*****424",
            "valid": false,
            "message": "License number must be unique from '*****321, *****424, *****033, *****424', but is '*****424'",
            "requirements": [
              {
                "fulfilled": false,
                "kind": "uniqueness",
                "message": "License number must be unique from '*****321, *****424, *****033, *****424', but is '*****424'",
                "metadata": {
                  "set": [
                    "*****321",
                    "*****424",
                    "*****033",
                    "*****424"
                  ]
                }
              },
              // ...
            ]
          },
          // ...
        },
        // ...
      ]
      // ...
    }
    // ...
  },
  // ...
}

Cause

The "License number must be unique..." error will occur within quote.profile.drivers[].licenseNumber.message and indicates that the license number for that driver does not satisfy our uniqueness requirement for this field among all drivers on the quote.

This means that one driver's license number matches the license number of another driver on the quote.

Resolution

To address this issue, your integration must de-duplicate the drivers on the quote in a subsequent update request (see Update quote):

  1. Identify all drivers with the same licenseNumber.value
  2. Choose which duplicate driver to keep
  3. Preserve prefillDriverId if it exists on any duplicate
  4. Submit an update request with one driver per duplicate set
  5. Confirm the returned licenseNumber.valid is true

How to choose the driver to keep

Your integration must therefore be able to determine how to merge the properties from these two drivers. We recommend determining which driver to keep out of the duplicates using the following precedence ordering:

  1. If possible, have the user select the driver to keep
  2. If one of the drivers is "Covered", prefer that driver
  3. Otherwise, if one of the drivers is "Excluded", prefer that driver

If either the kept driver or one of the duplicates has a prefillDriverId value present, then the kept driver details must include that field and its value.

Important Note

Any prefill-discovered drivers which are not explicitly included in any of your subsequent quote update requests for the quote will still remain on the quote's profile, since Root may require a decision for all prefill-discovered drivers before allowing the quote to be finalized. See this other FAQ doc for more details.

Example

Quote before finalizing

{
  "quote": {
    "id": "<uuid>",
    "status": "quoted",
    "kind": "estimated_quote",
    "profile": {
      "drivers": [
        {
          "status": {
            "value": "Covered",
            "valid": true,
            // ...
          },
          // ...
        }
      ],
      // ...
    },
    // ...
  },
  // ...
  "finalizable": true
}

Quote after finalizing

After finalizing, Root will automatically update the quote to include any drivers discovered during pre-fill. Therefore, some time after finalizing, you may receive a Quote GET response like the following:

{
  "quote": {
    "id": "<uuid>",
    "status": "quoted",
    "kind": "estimated_quote",
    "profile": {
      "drivers": [
        {
          "status": {
            "value": "Covered",
            "valid": true,
            // ...
          },
          // ...
        },
        {
          "status": {
            "value": "Undecided",
            "valid": false,
            // ...
          },
          // ...
        }
      ]
      // ...
    }
    // ...
  },
  // ...
  "finalizable": true
}

Quote after driver status decisions

We expect your integration to present these "Undecided" drivers to the user and have the user determine whether each driver should be one of:

  • Covered
  • Excluded
  • Not in household

After your integration determines each "Undecided" driver's status, your integration should update the quote with those new statuses. Then, the duplicate license number issue appears in the response:

{
  "quote": {
    "profile": {
      "drivers": [
        {
          // ...
          "licenseNumber": {
            "value": "*****424",
            "valid": false,
            "message": "License number must be unique from '*****321, *****424, *****033, *****424', but is '*****424'",
            "requirements": [
              {
                "fulfilled": false,
                "kind": "uniqueness",
                "message": "License number must be unique from '*****321, *****424, *****033, *****424', but is '*****424'",
                "metadata": {
                  "set": [
                    "*****321",
                    "*****424",
                    "*****033",
                    "*****424"
                  ]
                }
              },
              // ...
            ]
          },
          "status": {
            "value": "Covered",
            "valid": true,
            // ...
          },
          "prefillDriverId": {
            "value": null,
            "valid": true,
            // ...
          },
          // ...
        },
        {
          // ...
          "licenseNumber": {
            "value": "*****424",
            "valid": false,
            "message": "License number must be unique from '*****321, *****424, *****033, *****424', but is '*****424'",
            "requirements": [
              {
                "fulfilled": false,
                "kind": "uniqueness",
                "message": "License number must be unique from '*****321, *****424, *****033, *****424', but is '*****424'",
                "metadata": {
                  "set": [
                    "*****321",
                    "*****424",
                    "*****033",
                    "*****424"
                  ]
                }
              },
              // ...
            ]
          },
          "status": {
            "value": "Not in household",
            "valid": true,
            // ...
          },
          "prefillDriverId": {
            "value": "<some-uuid>",
            "valid": true,
            // ...
          },
          // ...
        },
        // ...
      ]
      // ...
    }
    // ...
  },
  // ...
}

Removing duplicate drivers

As mentioned above, these validation errors are arising because multiple drivers on the quote have the same license number. Therefore, we can resolve this issue by updating the quote to contain the same data as before, except for a couple key differences:

  • Only provide one driver for each duplicate set
  • For the kept driver, prefer the "Covered" driver for all details except prefillDriverId if on one of the duplicates

For instance, the Quote update request could look something like the following:

{
  "profile": {
    "drivers": [
      {
        "licenseNumber": "<duplicate-license-number-from-kept-driver>",
        "status": "Covered",
        "prefillDriverId": "<prefill-driver-id-from-the-duplicate-driver>",
        // all other fields from the kept driver
      },
      // ...
    ],
    // ...
  },
  // ...
}

Then, you should expect the quote to now be unblocked from being able to continue rating. Here's a sample Quote update response:

{
  "quote": {
    "id": "<uuid>",
    "status": "quoting",
    "kind": "bindable_quote",
    "profile": {
      "drivers": [
        {
          "licenseNumber": {
            "value": "*****424",
            "valid": true,
            // ...
          },
          "status": {
            "value": "Covered",
            "valid": true,
            // ...
          },
          // ...
        },
        // ...
      ]
      // ...
    }
    // ...
  },
  // ...
}