Backbone.js error: A 'url' property or function must be specified



This is actually an answer not a question. Using backbone.js heavily. Hit a nasty little critter but did not find an explanation of my particular case online. Hopefully this will save someone else some time.


Calling fetch() on a model pulled from a collection results in backbone error: "A 'url' property or function must be specified", even though both collection and model override sync().


AppPax.People = Backbone.Collection.extend({
    model: AppPax.Person,

AppPax.Person = AppPax.Model.extend({
    sync: function(method, model, options) {

        var response;

        switch (method) {
            case "read":    response = AppPax.getPerson(this.get("party_id"));

var c = new AppPax.People();
var person = c.find(function(person){
    return(person.get("party_id") == "5");
// everything seemingly successful up to here (but not really)

Resulting backbone error: "A 'url' property or function must be specified"

Misdirected Investigation

So after some debugging and investigation, including looking at the backbone.js code it was clear that Backbone was looking for the url property on the Person model and couldn't find it. However, my Person model overrides sync() and when a model overrides sync() Backbone doesn't demand that the model supply a url property/method.

I also noticed an anomaly: the models in the collection were never instantiated.

All my other stuff based on the exact same pattern had been working fine for a long time.

What to do?

Root Cause

The root cause turned out to be that in my module definition (AppPax) I had put the definition of Person after the definition of People (due to my now-not-so-useful habit of ordering code alphabetically).

When Backbone made an instance of People at my request, it apparently didn't know about AppPax.Person so it created its own version of Person based on the model properties returned by c.fetch() -- without all my good stuff in it, including my sync() method.

So when I tried to do person.fetch() it was using it's own, minimalist Person definition not mine, and that definition had no sync() method, so it looked for a url property/method on Person, didn't find it...choked.

So I defined AppPax.Person before AppPax.People and all worked fine.