How to detect subscription failure?

[Meteor 1.3 & React] I have a simple subscription, and I display a loading message while the data is being loaded. But I don’t know how to display error message if subscription failed.

export const MyAwesomeComponent = createContainer(() => {
  let sub = Meteor.subscribe('some-data');
  if (!sub.ready()) return { message: 'Loading...'};
  if (sub.failed()) return { message: 'Failed.' }; // How to do this?
  return {
	data: Data.find().fetch()
  }
}, MyInternalRenderComponent);

Problem is, the subscription object doesn’t have a failed() method, only a ready() query. How to pass the failure of a subscription as props in a createContainer() method?

I know the Meteor.subscribe method has an onStop callback for this case, but I don’t know how to glue it toghether that to pass a property.

Here’s a quick mod of your code to show how you could use the onStop callback to check for sub failure:

let subFailed = false;
export const MyAwesomeComponent = createContainer(() => {

  let sub = Meteor.subscribe('some-data', {
    onStop(error) {
      if (error) {
        subFailed = true;
      }
    }
  });
  
  let message = 'Loading...';
  if (subFailed) {
    message = 'Failed.';
  }

  return {
    message, 
    data: Data.find().fetch()
  }
  
}, MyInternalRenderComponent);
1 Like

Thank you. But this way one failure would make all the other instances of this component fail, right?

I know this is more than two years old but i’m stuck on the same problem and i wonder if there is yet a solution? As far as i can tell, the solution of @hwillson is not reactive and withTracker is not run again if onStop changes the subFailed variable. Am i wrong on this? Wouldn’t it make sense to add a .failed() state to the subscription like the ready() state? Or am i completely on the wrong track in trying to catch the subscription error?

It looks like OP got an answer on StackOverflow: https://stackoverflow.com/questions/36647681/meteor-1-3-react-detect-subscription-failure

We can modify @hwillson’s example a bit to make it reactive:

const subscriptionError = new ReactiveVar(false);
export const MyAwesomeComponent = withTracker(() => {

  if (!subscriptionError.get()) {
    let sub = Meteor.subscribe('some-data', {
      onStop(error) {
        if (error) {
          subscriptionError.set(error);
        }
      }
    }); 
  }
  
  return {
    data: Data.find().fetch(),
    error: subscriptionError.get(),
  }
  
}, MyInternalRenderComponent);

Keep in mind that if the subscription fails for one instance of this component, all of them will be affected, because they all close over a reference to the same subscriptionError variable. If you need to have one subscription per component instance, you could consider storing subscription information in the component’s state.

3 Likes