{"record":{"id":"95d9112d7b7b126a","repo":"vuejs/vuex","slug":"vuex-error-in-after-action-subscribers","errorCode":null,"errorMessage":"[vuex] error in after action subscribers: ","messagePattern":"\\[vuex\\] error in after action subscribers: ","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/store.js","lineNumber":178,"sourceCode":"      if (__DEV__) {\n        console.warn(`[vuex] error in before action subscribers: `)\n        console.error(e)\n      }\n    }\n\n    const result = entry.length > 1\n      ? Promise.all(entry.map(handler => handler(payload)))\n      : entry[0](payload)\n\n    return new Promise((resolve, reject) => {\n      result.then(res => {\n        try {\n          this._actionSubscribers\n            .filter(sub => sub.after)\n            .forEach(sub => sub.after(action, this.state))\n        } catch (e) {\n          if (__DEV__) {\n            console.warn(`[vuex] error in after action subscribers: `)\n            console.error(e)\n          }\n        }\n        resolve(res)\n      }, error => {\n        try {\n          this._actionSubscribers\n            .filter(sub => sub.error)\n            .forEach(sub => sub.error(action, this.state, error))\n        } catch (e) {\n          if (__DEV__) {\n            console.warn(`[vuex] error in error action subscribers: `)\n            console.error(e)\n          }\n        }\n        reject(error)\n      })\n    })","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/vuejs/vuex/blob/bd907467b8392d6671bb115738285ff7f63d0cf6/src/store.js#L160-L196","documentation":"An after action subscriber (subscribeAction after handler) threw inside the promise-resolution path of dispatch. Vuex catches it so the action's result still resolves, warning in development and logging the original error.","triggerScenarios":"subscribeAction({ after(action, state) { ... } }) throwing when an action resolves — commonly code assuming payload or state shape that changed, or async work that rejects synchronously inside the handler.","commonSituations":"Success-toast/analytics plugins breaking on actions whose payloads are Errors; subscribers calling router or other side effects that throw; version mismatch where after receives (action, state) but plugin expects options.","solutions":["Fix the handler using the error printed by console.error(e)","Add defensive checks/null guards on action.payload inside the handler","Wrap handler logic in try/catch inside the plugin","Update the plugin to the current Vuex subscriber API"],"exampleFix":"// before\nsubscribeAction: { after: (action) => toast(action.payload.message) }\n// after\nsubscribeAction: { after: (action) => { const p = action.payload; if (p && p.message) toast(p.message) } }","handlingStrategy":"try-catch","validationCode":"function safeAfterSubscriber(fn) {\n  return (action, state) => { try { fn(action, state) } catch (e) { console.warn('after subscriber failed', e) } }\n}\n// apply when registering: subscribeAction({ after: safeAfterSubscriber(myAfter) })","typeGuard":"function hasPayloadField(action, field) {\n  return Boolean(action && action.payload && field in action.payload)\n}","tryCatchPattern":"store.subscribeAction({\n  after(action, state) {\n    try { toast(action.payload?.message) }\n    catch (e) { console.warn('[vuex] after subscriber failed', e) }\n  }\n})","preventionTips":["Never assume action.payload shape; guard with optional chaining","Keep UI/analytics side effects failure-isolated in subscribers","Update plugins after Vuex upgrades (after handler signature changed historically)","Add dev tests that run each action and assert no subscriber warnings"],"tags":["vuex","plugin","action-subscriber","uncaught-exception"],"backgroundTag":"plugin-subscriber-crash","analyzedSha":"bd907467b8392d6671bb115738285ff7f63d0cf6","analyzedAt":"2026-08-28T21:38:57.320Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}