Once you get getUserMedia() working with audio and video constraints you immediately start hitting problems like:

  1. user has no webcam, just a microphone
  2. user has (accidentally) denied access to the webcam
  3. user plugs in the webcam/microphone after your getUserMedia() code has initialized
  4. the device is already used by another app on Windows
  5. Firefox only: the device is already used by another Firefox tab
  6. Chrome only: the user dismisses the privacy dialog

To tackle these situations the Media Capture and Streams spec that governs getUserMedia() defines several errors that you can look out for in your code (and correctly inform the user).

The table below lists the top 5 errors. They’re different between Firefox, which currently follows the spec more closely, and Chrome. On top of these 5, the spec also defines AbortError & SecurityError, but I was never able to trigger them.

Firefox 56 Chrome 62
NotFoundError DevicesNotFoundError
NotReadableError TrackStartError
OverconstrainedError ConstraintNotSatisfiedError
NotAllowedError PermissionDeniedError

NotFoundError

This one’s
very common
, it’s thrown in these 3 cases:

  1. when you’re requesting just a video track through constraints but the user does not have a webcam.

  2. when you request just an audio track but the user does not have a microphone device:

  • the computer or device has no sound card or
  • the computer or device has a sound card but the recording device is disabled because there’s no mic plugged in or
  • the recording device is disabled manually from the OS (can be done on Windows) but that’s rare.

Disabling audio recording devices in Windows 10

  1. when you’re requesting both video and audio tracks but the user does not have a webcam OR a microphone (it’s enough for one device to be missing for the error to be thrown)

Firefox will throw a MediaStreamError with it’s name property set to “NotFoundError” and the message “The object can not be found here”.

Chrome will throw a NavigatorUserMediaError with it’s name property set to “DevicesNotFoundError”.

NotReadableError

It most commonly happens on Windows when the browser tries to access the webcam or mic but they’re already in use (by Skype, etc.) –
on Windows where processes get exclusive access to the webcam
– but people have also been reporting the error showing up when using experimental constraints removed by Chrome or because of bugs in the Chrome screen recording code. On macOS, where processes share the webcam and microphone, I’ve only seen it reported by Firefox.

The Mozilla Developer Network Web Docs explanation covers all these situations:

Although the user granted permission to use the matching devices, a hardware error occurred at the operating system, browser, or Web page level which prevented access to the device.

On Windows Firefox will throw a MediaStreamError with it’s name property set to “NotReadableError” and it’s message property set to “Failed to allocate videosource” when another app (or Firefox tab) is using the webcam or microphone.

On Windows Chrome will throw a NavigatorUserMediaError with it’s name property set to “TrackStartError”, the non-spec Chrome-specific version, with no message. Different Chrome tabs can share the same webcam.

On macOS it’s only thrown by Firefox when another Firefox tab tries to get access to the webcam and mic. On macOs it’s paired with the message: “Concurrent mic process limit”.

OverconstrainedError

The specified constraints resulted in no candidate devices which met the criteria requested. The error is an object of type OverconstrainedError, and has a constraint property whose string value is the name of a constraint which was impossible to meet, and a message property containing a human-readable string explaining the problem.

It’s thrown when you’re requesting a constraint that can not be satisfied by the available hardware, for example a high frame rate or high resolution requested using the min or exact keywords.

Firefox will throw a MediaStreamError with it’s name property set to “OverconstrainedError” .

Chrome will throw a NavigatorUserMediaError with it’s name property set to “ConstraintNotSatisfiedError”, the non-spec Chrome-specific version.

Chrome & Firefox will return the requested resolution or the closest one when using ideal values but if you start using the min keyword with high values or the exact keyword with unsupported values you will immediately trigger the error.

The error object will also mention the constraint that could not be satisfied through the constraintName property and the message “Constraints could be not satisfied.”.

ConstraintNotSatisfiedError shown by Chrome in the console when requesting a an exact resolution of 1281x720

NotAllowedError

Is thrown when the user denies (or has previously denied) access to the webcam or microphone.

Firefox will throw a MediaStreamError with it’s name property set to “NotAllowedError” and the message “The request is not allowed by the user agent or the platform in the current context”.

Chrome will throw a NavigatorUserMediaError with it’s name property set to “PermissionDeniedError”.

Firefox webcam & mic permissions dialog

TypeError

It’s thrown when the constraints object passed to getUserMedia() is empty or has all tracks (audio, video or both) set to false.

Firefox will throw a MediaStreamError with it’s name property set to “TypeError” and the message “audio and/or video is required”.

Chrome will throw a “TypeError: Failed to execute ‘getUserMedia’ on ‘MediaDevices’: At least one of audio and video must be requested”.

PermissionDismissedError

It’s thrown by Chrome when the user closes the privacy dialog asking for mic and webcam access.

Chrome WebRTC getUSerMedia permission dialog

Dismissing the dialog is only possible on Chrome so there’s no equivalent error on other browsers. It’s not spec compliant so the error might be removed in Chrome 64 in the move towards spec compliant errors.

Handling these errors

Handling these errors is quite simple when using the newer promise based getUserMedia(). You can use the code below or this code pen.

var constraints = {
    video: false,
    audio: false
}
navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
    /* do stuff */
}).catch(function(err) {
    //log to console first 
    console.log(err); /* handle the error */
    if (err.name == "NotFoundError" || err.name == "DevicesNotFoundError") {
        //required track is missing 
    } else if (err.name == "NotReadableError" || err.name == "TrackStartError") {
        //webcam or mic are already in use 
    } else if (err.name == "OverconstrainedError" || err.name == "ConstraintNotSatisfiedError") {
        //constraints can not be satisfied by avb. devices 
    } else if (err.name == "NotAllowedError" || err.name == "PermissionDeniedError") {
        //permission denied in browser 
    } else if (err.name == "TypeError" || err.name == "TypeError") {
        //empty constraints object 
    } else {
        //other errors 
    }
});

The code starts out with false for both the video and audio track to immediately trigger the TypeError .

Spec compliant errors in Chrome 64

As per this Chromium issue Chrome will switch to spec compliant errors in Chrome 64. I will update this blog post as soon as it’s released. Chrome 64 will most likely be released in January but it is now available through the Chromium dev channel. Thank you Tsahi Levent-Levi for the heads up.