{"record":{"id":"a3c6b5b68e998e8f","repo":"emberjs/ember.js","slug":"transition-aborted","errorCode":"TRANSITION_ABORTED","errorMessage":"TransitionAborted","messagePattern":"TransitionAborted","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"info","filePath":"packages/router_js/lib/transition-aborted-error.ts","lineNumber":3,"sourceCode":"export interface TransitionAbortedError extends Error {\n  name: 'TransitionAborted';\n  code: 'TRANSITION_ABORTED';\n}\n\nexport function buildTransitionAborted() {\n  let error = new Error('TransitionAborted') as TransitionAbortedError;\n  error.name = 'TransitionAborted';\n  error.code = 'TRANSITION_ABORTED';\n  return error;\n}\n\nexport function isTransitionAborted(maybeError: unknown): maybeError is TransitionAbortedError {\n  return (\n    typeof maybeError === 'object' &&\n    maybeError !== null &&\n    (maybeError as TransitionAbortedError).code === 'TRANSITION_ABORTED'\n  );\n}\n\ninterface Abortable<T extends boolean> {","sourceCodeStart":1,"sourceCodeEnd":21,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/router_js/lib/transition-aborted-error.ts#L1-L21","documentation":"buildTransitionAborted creates the sentinel TransitionAbortedError (name 'TransitionAborted', code 'TRANSITION_ABORTED') thrown when a transition is aborted — typically by a redirect in a route hook (transitionTo/intermediateTransitionTo) or transition.abort(). Callers detect it via error.name/code to distinguish normal aborts from real failures.","triggerScenarios":"A route hook calls this.transitionTo (redirect), causing the original transition to be aborted; transition.abort() invoked; router internally aborts superseded transitions when a new one starts.","commonSituations":"Redirecting in beforeModel based on auth (throwing abort implicitly); double transitions racing (a new transition supersedes the running one); aborting in willTransition; test code not expecting the abort sentinel.","solutions":["Check error.name === 'TransitionAborted' (or code 'TRANSITION_ABORTED') and ignore/handle it separately from real errors.","Let redirects happen via returning the new transition or transitionTo from hooks rather than mixing with promises in ways that race.","Avoid starting multiple overlapping transitions; guard with a check like router.currentRouteName.","In .catch handlers, filter the sentinel before reporting errors."],"exampleFix":"// before\nthis.router.transitionTo('login').catch(e => report(e));\n// after\nthis.router.transitionTo('login').catch(e => {\n  if (e && e.name === 'TransitionAborted') return;\n  report(e);\n});","handlingStrategy":"try-catch","validationCode":"// Avoid racing transitions: skip if one is already underway to the same place\nif (router.currentRouteName === targetName) return;\nreturn router.transitionTo(targetName);","typeGuard":"function isTransitionAborted(e) { return !!e && e.name === 'TransitionAborted' && e.code === 'TRANSITION_ABORTED'; }","tryCatchPattern":"transition.catch(e => {\n  if (isTransitionAborted(e)) return; // expected on redirects\n  handleError(e);\n});","preventionTips":["Always filter TransitionAborted in transition .catch handlers.","Centralize redirects (auth guards) in one place to reduce racing transitions.","Don't call transitionTo while another transition is resolving unless intended.","Use error.name/code checks rather than message matching for the sentinel."],"tags":["routing","transition-aborted","ember"],"backgroundTag":"transition-aborted","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}