{"record":{"id":"2ae44ab06b0f7ca4","repo":"amark/gun","slug":"invalid-data-check-d-at-path-path","errorCode":null,"errorMessage":"Invalid data: ${check(d)} at ${path}.${path}","messagePattern":"Invalid data: (.+?) at (.+?)\\.(.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/put.js","lineNumber":32,"sourceCode":"\tvar s = as.state = as.state || Gun.state();\n\tif('function' == typeof data){ data(function(d){ as.data = d; gun.put(u,u,as) }); return gun }\n\tif(!as.soul){ return get(as), gun }\n\tas.$ = root.$.get(as.soul); // TODO: This may not allow user chaining and similar?\n\tas.todo = [{it: as.data, ref: as.$}];\n\tas.turn = as.turn || turn;\n\tas.ran = as.ran || ran;\n\t//var path = []; as.via.back(at => { at.get && path.push(at.get.slice(0,9)) }); path = path.reverse().join('.');\n\t// TODO: Perf! We only need to stun chains that are being modified, not necessarily written to.\n\t(function walk(){\n\t\tvar to = as.todo, at = to.pop(), d = at.it, cid = at.ref && at.ref._.id, v, k, cat, tmp, g;\n\t\tstun(as, at.ref);\n\t\tif(tmp = at.todo){\n\t\t\tk = tmp.pop(); d = d[k];\n\t\t\tif(tmp.length){ to.push(at) }\n\t\t}\n\t\tk && (to.path || (to.path = [])).push(k);\n\t\tif(!(v = valid(d)) && !(g = Gun.is(d))){\n\t\t\tif(!Object.plain(d)){ ran.err(as, \"Invalid data: \"+ check(d) +\" at \" + (as.via.back(function(at){at.get && tmp.push(at.get)}, tmp = []) || tmp.join('.'))+'.'+(to.path||[]).join('.')); return }\n\t\t\tvar seen = as.seen || (as.seen = []), i = seen.length;\n\t\t\twhile(i--){ if(d === (tmp = seen[i]).it){ v = d = tmp.link; break } }\n\t\t}\n\t\tif(k && v){ at.node = state_ify(at.node, k, s, d) } // handle soul later.\n\t\telse {\n\t\t\tif(!as.seen){ ran.err(as, \"Data at root of graph must be a node (an object).\"); return }\n\t\t\tas.seen.push(cat = {it: d, link: {}, todo: g? [] : Object.keys(d).sort().reverse(), path: (to.path||[]).slice(), up: at}); // Any perf reasons to CPU schedule this .keys( ?\n\t\t\tat.node = state_ify(at.node, k, s, cat.link);\n\t\t\t!g && cat.todo.length && to.push(cat);\n\t\t\t// ---------------\n\t\t\tvar id = as.seen.length;\n\t\t\t(as.wait || (as.wait = {}))[id] = '';\n\t\t\ttmp = (cat.ref = (g? d : k? at.ref.get(k) : at.ref))._;\n\t\t\t(tmp = (d && (d._||'')['#']) || tmp.soul || tmp.link)? resolve({soul: tmp}) : cat.ref.get(resolve, {run: as.run, /*hatch: 0,*/ v2020:1, out:{get:{'.':' '}}}); // TODO: BUG! This should be resolve ONLY soul to prevent full data from being loaded. // Fixed now?\n\t\t\t//setTimeout(function(){ if(F){ return } console.log(\"I HAVE NOT BEEN CALLED!\", path, id, cat.ref._.id, k) }, 9000); var F; // MAKE SURE TO ADD F = 1 below!\n\t\t\tfunction resolve(msg, eve){\n\t\t\t\tvar end = cat.link['#'];\n\t\t\t\tif(eve){ eve.off(); eve.rid(msg) } // TODO: Too early! Check all peers ack not found.","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/amark/gun/blob/552227599d47ba0493824b7fcf8a00c8cd6404ba/src/put.js#L14-L50","documentation":"Gun's put validation (run in src/put.js) walks each value being written. If a value at some path is neither a valid primitive (valid(d)) nor a Gun graph node (Gun.is(d)) nor a plain object (Object.plain(d)), it is rejected as invalid data and err is raised with the offending value and its graph path. Gun only stores primitives, nodes, and plain objects — class instances, functions, undefined, Dates, etc. are not serializable graph data.","triggerScenarios":"gun.put() or gun.get(...).put(...) with a field value that is a Date, function, class instance, undefined, NaN or other non-plain object; deeply nested non-plain values discovered while walking the todo path (path shown as via-path + to-path in the message).","commonSituations":"Storing Date objects instead of timestamps; storing a Map/Set or class instance returned from an ORM; writing values still wrapped in a Proxy or reactive framework object; accidentally putting a function or undefined from an unset variable; Vue/React state objects passed straight into put.","solutions":["Convert non-plain values to primitives before put: dates → ISO strings or epoch numbers","Extract plain data from class instances/Maps/Sets (JSON round-trip or explicit toObject)","Ensure undefined fields are removed or replaced with null/string placeholders","For large shared objects, store them as their own node (soul) and link by reference instead of nesting"],"exampleFix":"// before\nuser.get('profile').put({ createdAt: new Date(), meta: someClassInstance });\n// after\nuser.get('profile').put({\n  createdAt: new Date().toISOString(),\n  meta: JSON.parse(JSON.stringify(someClassInstance))\n});","handlingStrategy":"validation","validationCode":"function assertPutSafe(value, depth = 0) {\n  if (value === null || ['string','number','boolean'].includes(typeof value)) return;\n  if (depth > 5) throw new Error('too deep for gun put');\n  const proto = Object.getPrototypeOf(value);\n  if (value instanceof Date || typeof value === 'function' || value instanceof Map || value instanceof Set) {\n    throw new Error('non-graph value: ' + value);\n  }\n  if (proto === Object.prototype || proto === null || Array.isArray(value)) {\n    Object.values(value).forEach(v => assertPutSafe(v, depth + 1));\n    return;\n  }\n  throw new Error('class instances are not plain objects: ' + value);\n}","typeGuard":"const isPutSafeValue = (v) =>\n  v === null || ['string','number','boolean'].includes(typeof v) ||\n  (typeof v === 'object' && (v.constructor === Object || v instanceof Date === false) && Object.getPrototypeOf(v) === Object.prototype);","tryCatchPattern":"gun.get('node').put(data, ack => {\n  if (ack && ack.err) {\n    if (String(ack.err).startsWith('Invalid data:')) {\n      console.error('gun rejected non-plain value at:', ack.err);\n    }\n    return;\n  }\n});","preventionTips":["Convert Dates to ISO strings/epoch numbers before put","Serialize class instances, Maps, Sets with JSON round-trip","Never put functions, undefined, or framework proxies","Keep node payloads small and plain; link large objects by soul"],"tags":["gun","put","validation","data-shape"],"backgroundTag":"invalid-graph-data","analyzedSha":"552227599d47ba0493824b7fcf8a00c8cd6404ba","analyzedAt":"2026-09-02T18:40:58.370Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}