Object property becomes null after chrome.storage.sync.set


I'm building a chrome extension and have encountered a bug I cannot wrap my head around. The problem is a single object property that becomes null in chromes' storage.

I'm testing this by doing:

console.log("pre-storage", settings);
var obj = {};
obj[storage_key] = settings;

chrome.storage.sync.set(obj, function() {
    chrome.storage.sync.get(storage_key, function(data) {
        console.log("post-storage", data[storage_key]);
    });
});

This is the output:

pre-storage, Object {
    ...
    soundClip: Object {
        options: Array[5],
        selected: Object {
            label: "Soft2",
            value: "snd/soft2.wav"
        }
    }
}

post-storage, Object {
    ...
    soundClip: Object {
        options: Array[5],
        selected: null
    }
}

Storing JSON.parse(JSON.stringify(obj)) instead of obj directly seems to fix this. Anyone have any ideas what might cause this? Any help is appreciated!

Edit: Making a deep copy of obj does not fix it.

Edit2: I should expand on how settings.soundClip is set. I'm using Angular (1.x) and I'm using a custom select directive. The stripped down directive looks like this:

function mySelect() {
    return {
        restrict: "E",
        templateUrl: "mySelect.html",
        scope: {
            options: "=",
            selected: "="
        },
        link: function (scope) {
            scope.select = function (item) {
                scope.selected = item;
            };
        }
    }
}

Directive template view (mySelect.html):

<div>
    <div ng-repeat="item in options track by $index"
         ng-click="select(item)">
    </div>
</div>

The properties are then two-way bound like this:

<my-select selected="settings.soundClip.selected"
           options="settings.soundClip.options">
</my-select >

Since calling JSON.parse(JSON.stringify(obj)) seems to fix it, my guess is that you're having a problem with encoding your settings object with a variable instead of a string. See the answer here which might help.


Is it possible that the total quota (or per item) is being hit? Consider displaying the runtime.lastError on the set callback to see if there are any error messages.

chrome.storage.sync.set(obj, function() {

  console.log('Error', runtime.lastError);

  chrome.storage.sync.get(storage_key, function(data) {
    console.log("post-storage", data[storage_key]);
  });
});

See the limits here chrome.storage.sync.set