Okay, I tracked it down.  If `InvalidError` is passed back in the `reject` it will throw the exception which will bubble up the call stack instead of hitting the failure route of the promise.  So wrapping the reject in an `Ember.run.next` makes it so `save` completes without failure and the failure hits the failure route of the promise instead of crashing the save.