Skip to content

Handling errors with the vision API is confusing #1450

Description

@JustinBeckwith

I was building an app with the vision API, and noticed that I'm not getting errors in the callback of the detect method. After some console.log debugging, I saw the list of errors came back in the payload of the call - not an err object. This is really unexpected behavior. Can we just change this to return errors like a normal API?

Activity

  1. jgeewax commented on Jul 26, 2016

    @jgeewax
    Contributor

    Ew - yes, errors should come back in the errors object... @stephenplusplus

  2. stephenplusplus commented on Jul 26, 2016

    @stephenplusplus
    Contributor

    The problem here is a single API call can return 1 error, but 9 successes. If we communicate it as an error, I'm worried the user will ignore the successes. I do think there's a better way to do this, but I'm not sure what that is. Any ideas (in code)?

  3. jgeewax commented on Jul 26, 2016

    @jgeewax
    Contributor

    Why would it return errors ?

    Can we make it a stream of results rather than one big one? Do the successes first, then the errors?

  4. JustinBeckwith commented on Aug 1, 2016

    @JustinBeckwith
    ContributorAuthor

    I actually think an EventEmitter style API here would be great. It solves the issue of batching pretty nicely.

  5. stephenplusplus commented on Aug 2, 2016

    @stephenplusplus
    Contributor

    Just so we know where we're at currently, this is how we do it now:

    vision.detect(['img.jpg', 'img-2.jpg'], ['faces', 'labels', 'safeSearch'], function(err, detections) {
      if (err) {
        // The API returned an error
        return;
      }
    
      // If we're here, the API gave us a 200
    
      var firstImageDetections = detections[0];
    
      if (firstImageDetections.faces.errors.length) {
        // Facial detection failed for the first image
      }
    
      if (firstImageDetections.labels.errors.length) {
        // Label detection failed for the first image
      }
    
      if (firstImageDetections.safeSearch.errors.length) {
        // SafeSearch detection failed for the first image
      }
    
      var secondImageDetections = detections[1];
    
      if (secondImageDetections.faces.errors.length) {
        // Facial detection failed for the second image
      }
    
      if (secondImageDetections.labels.errors.length) {
        // Label detection failed for the second image
      }
    
      if (secondImageDetections.safeSearch.errors.length) {
        // SafeSearch detection failed for the second image
      }
    });

    I recognize this is awkward if you don't know that each detection can have different errors, but once you do, I think this way is actually the path of least surprise. If the user is asking for multiple detections for multiple images in one request, they should already be handling each requested detection for each image independently. They might not want to call the whole thing a failure if something went wrong with just one of those requests.

    @JustinBeckwith do you mean:

    vision.detectFaces('image.jpg')
      .on('error', function(err) {})
      .on('detections', function(detections) {});

    I'm not big on jumping to an EventEmitter here, mostly because it would be a deviation
    from the patterns in the rest of our API. But maybe seeing an example that would make the user's life easier would convince me... I really do want to make this as easy as possible.

    Here's my "worst case scenario" using EE. Let's say the face detection from img.jpg fails and the label detection from img-2.jpg fails.

    vision.detect(['img.jpg', 'img-2.jpg'], ['faces', 'labels', 'safeSearch'])
    
      // Do we emit this for each error or group errors together?
      .on('error', function(err) {
        // Some kind of error occurred, either an API error or a detection failure.
        // How does the user know the difference?
    
        // If it is a detection failure, how do they know which image / feature failed?
    
        // Ideas:
        err.detectionType = 'face';
        err.image = 'img.jpg';
        err.message = 'Facial detection error message';
    
        // Then on the second emit:
        err.detectionType = 'label';
        err.image = 'img-2.jpg';
        err.message = 'Label detection error message';
      })
    
      // All detections are in. (Or do we emit once per detection?)
      .on('detections', function(detections) {
        var firstImageDetections = detections[0];
        firstImageDetections = {
          labels: [...],
          safeSearch: {...}
        };
    
        var secondImageDetections = detections[1];
        secondImageDetections = {
          faces: [...],
          safeSearch: {...}
        }
      });

    The separation of error / success seems nice, but I'm wondering if the user would find it difficult to manage having to match the successes/failures to see what features each image ended up with. I think having it in one place is easier to deal with.

  6. JustinBeckwith commented on Aug 8, 2016

    @JustinBeckwith
    ContributorAuthor

    Nice! One idea is to support both. vision.detect() could return an EventEmitter, and you could also take a callback as the final parameter. If you use the callback approach, one failure fails the whole call. If you use the EventEmitter, you can sift through and choose only successes if you like.

    Eh?

  7. stephenplusplus commented on Oct 21, 2016

    @stephenplusplus
    Contributor

    #1644 will track this. Basically, it's the same issue, just more generally applied to the other areas of our API that have this same pattern.

  8. added a commit that references this issue on Feb 3, 2026
  9. added a commit that references this issue on Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

api: visionIssues related to the Cloud Vision API.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions