Angular UI router handling 404s


I have an app with a service which wraps my API calls:

var ConcernService = {
    get: function (items_url, objId) {
        var defer = $q.defer();
        $http({method: 'GET', 
            url: api_url + items_url + objId}).
            success(function (data, status, headers, config) {
            }).error(function (data, status, headers, config) {
                console.log('ConcernService.get status',status);
        return defer.promise;

and I'm using UI-Router to transition between states:


    .config( function ($stateProvider, $urlRouterProvider) {


        $stateProvider.state('project', {
        url: '/project/:projectId/',
        resolve: {
            project: function ($stateParams, ConcernService) {
                return ConcernService.get('projects/', $stateParams.projectId);
        views: {

I'm moving from using the normal Angualr router and I'm having difficulty understanding how to implement 404s. I can see the ConcernService throwing the console.log status as rejected, but how do I catch this in the state router?

Any help much appreciated.

Problem courtesy of: Darwin Tech


The otherwise() rule is only invoked when no other route matches. What you really want is to intercept the $stateChangeError event, which is what gets fired when something goes wrong in a state transition (for example, a resolve failing). You can read more about that in the state change event docs.

The simplest implementation for what you're trying to do would be something like this:

$rootScope.$on('$stateChangeError', function(event) {

Also, since $http itself is built on promises (which resolve resolves), your ConcernService method can be simplified down to a one-liner (I realize you expanded it for debugging purposes, but you could have just as easily chained it, just FYI):

var ConcernService = {

  get: function (items_url, objId) {
    return $http.get(api_url + items_url + objId);
Solution courtesy of: Nate Abele


You can also try something like this and see if it works for you. You may need to adjust to your needs:

.state('otherwise', {
    abstract: true,
    templateUrl: 'views/404.html'
.state('otherwise.404', {
    url: '*path',
    templateUrl: 'views/404.html'
Discussion courtesy of: ucsarge

I differ between two 404 states:


  • show 404 page depending on server response HTTP Code 404
  • important to define no URL, so that user stays on URL where the error happened


  • URL is not found by angular ui router (none of defined URLs)

Code for Angular UI-Router state:

  .state('404server', {
    templateUrl: '/views/layouts/404.html'
  .state('404client', {
    url: '*path',
    templateUrl: '/views/layouts/404.html'

Code in $httpProvider interceptor:

if(response.status === 404) {

And why I used $injector instead of $state is explained here.

Discussion courtesy of: Betty St

The $urlRouterProvider only works like a $watch to $location and if the actual URL matches one of the rules defined in the .config() function then it will redirect to the specified route.

Here's what I recommend, define "/404/" as a state:

$stateProvider.state('404', {

And inside the reject() function move to 404 state

 if(status == '404'){

You will have to add ui-router as dependency of the project module and use the $state provider in your controller in order to be able to use $state.transitionTo()

Here's some info:

Discussion courtesy of: Alejandro Figueroa

I managed to handle 404 without using $urlRoutProvider since I'm only using states by testing $state.transistion:

angular.module("app", []).run(["$state", "$rootScope", function($state, $rootScope) => {
    $rootScope.$on("$locationChangeSuccess", function() {
        if (!$state.transition) {
Discussion courtesy of: Claudio Mezzasalma


.state('error', {
  url: "/page-not-found",
  templateUrl: "templates/error.html",
  controller: "errorController"

Will handle your page not found problem.

If you want to raise 404 found purposefully use the state or url. We have created a separate controller just if you want to perform any operations.

Discussion courtesy of: BASAVANA GOUDA S PATIL

This recipe can be found in it's original form on Stack Over Flow.