{"record":{"id":"3208fae8d131dad4","repo":"hcengineering/platform","slug":"set-is-not-allowed-in-model","errorCode":null,"errorMessage":"Set is not allowed in model","messagePattern":"Set is not allowed in model","errorType":"exception","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"foundations/core/packages/core/src/proxy.ts","lineNumber":39,"sourceCode":"      const value = target[mixin._id]?.[property]\n      if (value === undefined) {\n        return ancestorProxy !== null ? ancestorProxy.get?.(target, property, receiver) : target[property]\n      }\n      return value\n    }\n  }\n}\n\nexport function freeze (value: any): any {\n  if (value != null && typeof value === 'object') {\n    if (Array.isArray(value)) {\n      return value.map((it) => freeze(it))\n    }\n    if (value instanceof Map) {\n      throw new PlatformError(unknownError('Map is not allowed in model'))\n    }\n    if (value instanceof Set) {\n      throw new PlatformError(unknownError('Set is not allowed in model'))\n    }\n    return new Proxy(value, _createFreezeProxy(value))\n  }\n  return value\n}\n/**\n * @internal\n */\nexport function _createFreezeProxy (doc: Doc): ProxyHandler<Doc> {\n  return {\n    get (target: any, property: string, receiver: any): any {\n      const value = target[property]\n      return freeze(value)\n    },\n    set (target, p, newValue, receiver): any {\n      throw new PlatformError(unknownError('Modification is not allowed'))\n    },\n    defineProperty (target, property, attributes): any {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/core/packages/core/src/proxy.ts#L21-L57","documentation":"Just like Map, JavaScript Set instances are not representable in the model: freeze() recursively proxies object values it hands out and cannot wrap a Set, so it throws this PlatformError. Docs must contain plain objects, arrays, and primitives only. The error fires when a Set is reached while reading model data through a frozen proxy.","triggerScenarios":"Assigning a Set to a document field (e.g. { members: new Set(ids) }) and then reading the doc through the model proxy (freeze is invoked on get), including via derived attribute getters such as darkPalette/avatarDarkColors.","commonSituations":"Using Set to get deduplication in domain data stored on docs; deserialization paths that produce Sets; refactoring a field from array to Set for convenience.","solutions":["Store arrays instead: [...mySet] when writing the field, and dedupe on write if needed.","Keep Sets in application code, converting to/from arrays at the model boundary.","Normalize deserialized data so Sets become arrays before they touch the model."],"exampleFix":"// before\nconst doc = { members: new Set(userIds) }\n// after\nconst doc = { members: [...new Set(userIds)] }","handlingStrategy":"validation","validationCode":"function toModelSafeArray(v: unknown): unknown {\n  if (v instanceof Set) return [...v]\n  if (v instanceof Map) return Object.fromEntries(v)\n  return v\n}\nconst doc = { members: toModelSafeArray(memberSet) }","typeGuard":"function isModelSafeValue(v: unknown): boolean {\n  return v == null || typeof v !== 'object' || (! (v instanceof Map) && !(v instanceof Set))\n}","tryCatchPattern":"try {\n  use(doc.members)\n} catch (e) {\n  if (e instanceof PlatformError && e.message.includes('Set is not allowed in model')) {\n    console.error('Store arrays, not Sets, in doc fields: [...mySet]')\n  } else throw e\n}","preventionTips":["Use arrays for stored collections; apply dedup with new Set(arr) only transiently.","Normalize deserialization output (some libs yield Sets) before saving to docs.","Lint against new Set(...) appearing in doc field assignments."],"tags":["model","proxy","immutability"],"backgroundTag":"map-not-allowed-in-model","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}