Method validation

Hello!
I am learning meteor and trying to understand how to implement crud life cycle. When I make my methods server only everything works as expected, I reject validation error in promise and it’s caught by Method.apply callback

Meteor.apply('shops.save', [data], options, (error, response) => {
  if (error) {
    this.setState({ error: error.reason })
  }
})

But I want to make use of optimistic UI and use throwStubExceptions and made methods available for both client and server. This is where things start to get confusing - I am expecting client run simulation and catch the same error which would prevent server code to be executed. Instead I see error being thrown in console it is not caught by callback and server call is executed same as if methods were pure server. Please help me make sense of how meteor works for now I can’t get how to make it all work together!
Method code:

'shops.save'({ id, ...data }) {
    const validationContext = 'shops.save'
    return new Promise(function (resolve, reject) {
      Shops.upsert(id, {
        $set: data
      }, { validationContext }, function(error, result) {
        if (error) {
          // get messages
          const invalidKeys = error.invalidKeys
          if (!invalidKeys)
            reject(error)

          // constructing messages
          const context = Shops.simpleSchema().namedContext(validationContext)
          const errors = invalidKeys.reduce((errors, key) => {
            errors.push(context.keyErrorMessage(key.name))
            return errors
          }, [])

          reject (new ValidationError(invalidKeys, errors.join(', ')))
          //reject(new Meteor.Error('shops.save.validation', errors.join(', '), errors))
        }

        resolve(result)
      })
    })
  }