You are right, the problem is that you restore the cannes by loading json, which contains the wrong value for the fill property, explicitly:
"fill":{"ok":true,"format":"hex6","_tc_id":258,"alpha":1}
This object probably comes from the TinyColor serialization
Unfortunately, this cannot be correctly interpreted using fabricjs and cannot be converted back to hexadecimal (see TinyColor sources if you need to read this point)
I create this fiddle to show how a similar error can be reproduced; suppose we have TinyColor
var t = tinycolor("#ff0000");
We make a mistake if we use this TinyColor object as the value of the fill property (i.e. fill: t ), for example:
canvas.add(new fabric.Rect({ width: 50, height: 50, fill: t, top: 100, left: 100 }));
by serializing the canvas, we get JSON that contains:
"fill":{"ok":true,"format":"hex","_tc_id":0,"alpha":1},
but this will not work, and the actual fill rendered as black (default) instead of our color (red).
The correct approach is to use fill: t.toHexString() :
canvas.add(new fabric.Rect({ width: 50, height: 50, fill: t.toHexString(), top: 150, left: 150 }))
this works fine (the rectangle is red), in addition, serializing the canvas, we get JSON, which contains:
"fill":"#ff0000"
so this will work fine even if you restore jerry cans from JSON.
EDIT
In the end, I propose to fix the problem in origini, but , if you have to deal with a buggy-json string, you can also intercept the problem as follows:
if (typeof hex == "object" && hex.hasOwnProperty("_tc_id")) { alert("no color available; return a default such as fill:'none'"); }
like in this fork the column in question