UI-Router is a routing framework for AngularJS (and later versions too) that allows you to create states and views for your application. It’s more powerful than the basic $routeProvider
and supports nested views, abstract states, and more.
When you define a state in UI-Router, you give it a state name (e.g., 'home'
, 'dashboard.user'
, 'profile.edit'
). You then navigate to that state using:
$state.go('stateName');
or via a link like:
<a ui-sref="stateName">Go to State</a>
But if the framework cannot find that state, you’ll get the error:
“Error: Could not resolve ‘stateName'”
What Does This Error Mean?
It means that you are trying to navigate to a state that UI-Router doesn’t recognize—i.e., it hasn’t been defined yet in the application when you tried to access it.
Common Causes (Explained in Depth)
Let’s go through this step-by-step.
1️⃣ The State Is Not Registered
The most common reason. You tried to access a state like dashboard.settings
, but in your state configuration, you never defined it.
Fix:
Make sure you have defined the state properly:
$stateProvider
.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard.html',
controller: 'DashboardCtrl'
})
.state('dashboard.settings', {
url: '/settings',
templateUrl: 'settings.html',
controller: 'SettingsCtrl'
});
If you forget to define 'dashboard.settings'
, then calling $state.go('dashboard.settings')
will throw the error.
2️⃣ Typo in State Name
Even a small typo will cause this error. For example, if you defined 'dashboard.setting'
(without the s
) but used 'dashboard.settings'
, you’ll get this error.
Fix:
Double-check the spelling of your state names everywhere: in $state.go()
, ui-sref
, and state definitions.
3️⃣ State File Not Loaded
In large applications using lazy-loading or modules, your state definitions might be in separate files. If the file where the state is defined isn’t loaded before the transition happens, UI-Router won’t find the state.
Fix:
Make sure that all JavaScript files containing your state definitions are included before you navigate to that state.
If you’re using lazy loading with ocLazyLoad, ensure the module is loaded before calling $state.go()
.
Example using ocLazyLoad
:
.state('lazyState', {
url: '/lazy',
templateUrl: 'lazy.html',
controller: 'LazyCtrl',
resolve: {
loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load('lazyCtrl.js');
}]
}
});
4️⃣ ui-sref Binding Incorrectly
If you write ui-sref="{{ stateName }}"
in HTML, this won’t work because ui-sref
doesn’t work like ng-href
. It expects the expression directly, not a string interpolation.
Wrong:
<a ui-sref="{{ stateName }}">Go</a>
Right:
<a ui-sref="stateName">Go</a>
Or if you’re using dynamic binding, use the directive:
<a ng-click="$state.go(stateName)">Go</a>
5️⃣ Abstract States Accessed Directly
If your state is marked abstract: true
, you cannot navigate to it directly. It’s meant to be a base state for child states.
Example:
$stateProvider
.state('admin', {
abstract: true,
template: '<ui-view/>'
})
.state('admin.users', {
url: '/users',
templateUrl: 'users.html'
});
Calling $state.go('admin')
will throw the error.
Fix:
Navigate to a concrete child state, like 'admin.users'
.
6️⃣ State Not Part of Loaded Module
If you’re using modules (angular.module('app', [...])
) and your state is defined in another module (e.g., userModule
), make sure it’s included in your app module’s dependency array.
Fix:
angular.module('app', ['ui.router', 'userModule']);
Otherwise, UI-Router never sees the state definition.
7️⃣ Nested States and URL Confusion
When defining nested states, people often misconfigure the URLs or forget to include ui-view
in the parent template.
Example:
.state('parent', {
url: '/parent',
templateUrl: 'parent.html'
})
.state('parent.child', {
url: '/child',
templateUrl: 'child.html'
});
Make sure parent.html
contains:
<div ui-view></div>
Otherwise, child views will not render, and navigating to parent.child
might break.
Debugging Tips
- Use
$state.get()
in Console It returns all registered states. jsCopyEditconsole.log($state.get());
See if your desired state is listed. - Check Dev Tools > Network Tab Make sure all JavaScript files (especially ones defining states) are successfully loaded.
- Use
console.log()
in config blocks Add logging inside your.config()
block to see if your state definitions are running. - Check Your Module Definitions Make sure all modules with
.state()
definitions are bootstrapped correctly.
Summary and Checklist
Problem | Solution |
---|---|
State not defined | Define the state using $stateProvider.state() |
Typo in name | Double-check state names in code |
File not loaded | Load state definition JS file before navigation |
Incorrect ui-sref | Use ui-sref="stateName" without {{}} |
Navigating to abstract state | Navigate to child state instead |
Missing module dependency | Include module in main app |
Missing ui-view | Ensure parent templates have <ui-view> |
URL mismatch | Ensure URL fragments are correctly defined |