balderdashy/sails · info
Warning: route `${address}` should explicitly declare `skipA
Error message
Warning: route `${address}` should explicitly declare `skipAssets: true` or `skipAssets: false` to ensure correct handling of assets! What it means
For catch-all style routes (ending in `/*` or `/?`, or regex-syntax `r|...` routes) bound with permissive verbs (all/get/head/options) where the target omits `skipAssets`, Sails warns because static asset requests (images, js, css) may accidentally match the route. Explicitly declaring `skipAssets: true` or `false` makes intent clear.
Source
Thrown at lib/router/index.js:377
// Updated the sorted route address cache
sortedRouteAddresses = sortRouteAddresses(_.keys(this.explicitRoutes));
// Iterate over each address and bind the route that the address is for.
_.each(sortedRouteAddresses, function(address) {
var target = self.explicitRoutes[address];
var verb = detectVerb(address).verb;
// If the route address ends in a pattern var (e.g. /:id) or a wildcard (i.e. /*)
// and it declares a method that could be used to request an asset, and the route
// doesn't explicitly declare `skipAssets` true or false, then it should!
var shouldDeclareSkipAssets = (
_.isUndefined(target.skipAssets) &&
(address.match(/\/\*\/?$/) || address.match(/^r\|/)) &&
(!verb || _.contains(['all', 'get', 'head', 'options'], verb))
);
if (shouldDeclareSkipAssets) {
sails.log.warn('Warning: route `' + address + '` should explicitly declare `skipAssets: true` or `skipAssets: false` to ensure correct handling of assets!');
sails.log.warn('See http://sailsjs.com/docs/concepts/routes/url-slugs for more info.');
console.log();
}
self.bind(address, target);
});
// Fired after static routes are bound
sails.emit('router:after');
};
/**
* Given a route target configuration, return an action identity for that target.
* @param {Dictionary|String} target The route target to get an action identity for
* @return {String} An action identity like `user/find`
*/
Router.prototype.getActionIdentityForTarget = function getActionIdentityForTarget(target) {View on GitHub (pinned to 7b76422cc2)
Solutions
- Add `skipAssets: true` to the route target so it ignores static asset URLs
- Add `skipAssets: false` explicitly if you truly want the route to handle asset paths
- Scope the catch-all pattern more narrowly (e.g. `/page/*`) to avoid the ambiguity
Example fix
// before
'GET /*': 'PageController.show'
// after
'GET /*': { view: 'homepage', skipAssets: true } Defensive patterns
Strategy: validation
Validate before calling
function assertSkipAssets(routes) {
for (const [addr, target] of Object.entries(routes)) {
if (/\*\/?$/.test(addr) && target && target.skipAssets === undefined) {
console.warn(`Route ${addr} should declare skipAssets: true|false`);
}
}
} Prevention
- Always set skipAssets explicitly on wildcard routes
- Scope catch-alls narrowly instead of using bare /*
- Review the URL-slugs docs when designing route tables
When it happens
Trigger: Binding e.g. `'GET /*': 'PageController.show'` or any `/*`-style route without a `skipAssets` property in the target object.
Common situations: Catch-all routing for SPAs or CMS-style pages; developers forget that without skipAssets the route will also swallow requests for static files.
Related errors
- See http://sailsjs.com/docs/concepts/routes/url-slugs for mo
- Cannot call res.render() - `req._sails.renderView` was not a
- E_VIEW_INFER
- i18n hook has disabled itself due to misconfiguration -- ret
- Invalid CORS settings for route ${route}
AI-assisted analysis of balderdashy/sails@7b76422cc2 (2026-09-01).
Data as JSON: /api/errors/044980fe7888e96b.
Report an issue: GitHub.