hcengineering/platform · error · PlatformError

Set is not allowed in model

Error message

Set is not allowed in model

What it means

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.

Source

Thrown at foundations/core/packages/core/src/proxy.ts:39

      const value = target[mixin._id]?.[property]
      if (value === undefined) {
        return ancestorProxy !== null ? ancestorProxy.get?.(target, property, receiver) : target[property]
      }
      return value
    }
  }
}

export function freeze (value: any): any {
  if (value != null && typeof value === 'object') {
    if (Array.isArray(value)) {
      return value.map((it) => freeze(it))
    }
    if (value instanceof Map) {
      throw new PlatformError(unknownError('Map is not allowed in model'))
    }
    if (value instanceof Set) {
      throw new PlatformError(unknownError('Set is not allowed in model'))
    }
    return new Proxy(value, _createFreezeProxy(value))
  }
  return value
}
/**
 * @internal
 */
export function _createFreezeProxy (doc: Doc): ProxyHandler<Doc> {
  return {
    get (target: any, property: string, receiver: any): any {
      const value = target[property]
      return freeze(value)
    },
    set (target, p, newValue, receiver): any {
      throw new PlatformError(unknownError('Modification is not allowed'))
    },
    defineProperty (target, property, attributes): any {

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Store arrays instead: [...mySet] when writing the field, and dedupe on write if needed.
  2. Keep Sets in application code, converting to/from arrays at the model boundary.
  3. Normalize deserialized data so Sets become arrays before they touch the model.

Example fix

// before
const doc = { members: new Set(userIds) }
// after
const doc = { members: [...new Set(userIds)] }
Defensive patterns

Strategy: validation

Validate before calling

function toModelSafeArray(v: unknown): unknown {
  if (v instanceof Set) return [...v]
  if (v instanceof Map) return Object.fromEntries(v)
  return v
}
const doc = { members: toModelSafeArray(memberSet) }

Type guard

function isModelSafeValue(v: unknown): boolean {
  return v == null || typeof v !== 'object' || (! (v instanceof Map) && !(v instanceof Set))
}

Try / catch

try {
  use(doc.members)
} catch (e) {
  if (e instanceof PlatformError && e.message.includes('Set is not allowed in model')) {
    console.error('Store arrays, not Sets, in doc fields: [...mySet]')
  } else throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/3208fae8d131dad4. Report an issue: GitHub.