{"record":{"id":"96a1011cb5a8c8cc","repo":"toeverything/AFFiNE","slug":"reactiveproxyerror","errorCode":"ReactiveProxyError","errorMessage":"flatY2Native does not support Y.Map as value of Y.Map","messagePattern":"flatY2Native does not support Y\\.Map as value of Y\\.Map","errorType":"exception","errorClass":"BlockSuiteError","httpStatus":null,"severity":"error","filePath":"blocksuite/framework/store/src/reactive/flat-native-y/initialize.ts","lineNumber":37,"sourceCode":"}: InitializeDataOptions): UnRecord => {\n  const root: UnRecord = {};\n  Array.from(yMap.entries()).forEach(([key, value]) => {\n    if (key.startsWith('sys')) {\n      return;\n    }\n    const keys = keyWithoutPrefix(key).split('.');\n    const firstKey = keys[0];\n\n    let finalData = value;\n    if (Boxed.is(value)) {\n      finalData = transform(firstKey, new Boxed(value), value);\n    } else if (value instanceof YArray) {\n      finalData = transform(firstKey, value.toArray(), value);\n    } else if (value instanceof YText) {\n      const next = new Text(value);\n      finalData = transform(firstKey, next, value);\n    } else if (value instanceof YMap) {\n      throw new BlockSuiteError(\n        BlockSuiteError.ErrorCode.ReactiveProxyError,\n        'flatY2Native does not support Y.Map as value of Y.Map'\n      );\n    } else {\n      finalData = transform(firstKey, value, value);\n    }\n    const allLength = keys.length;\n    void keys.reduce((acc: UnRecord, key, index) => {\n      if (!acc[key] && index !== allLength - 1) {\n        const path = keys.slice(0, index + 1).join('.');\n        const data = getProxy({} as UnRecord, root, path);\n        acc[key] = data;\n      }\n      if (index === allLength - 1) {\n        acc[key] = finalData;\n      }\n      return acc[key] as UnRecord;\n    }, root);","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/blocksuite/framework/store/src/reactive/flat-native-y/initialize.ts#L19-L55","documentation":"Thrown by initializeData in the flat-native-y reactive layer when a block's Yjs map contains a value that is itself a Y.Map. The flat-data model flattens nested objects into dotted keys (e.g. 'prop:style.color') and only supports scalars, YArray, YText, and Boxed as leaf values; a nested Y.Map has no flat representation, so initialization refuses it.","triggerScenarios":"Using a block whose schema declares isFlatData:true and storing a prop whose value is a Y.Map (e.g. directly assigning a Y.Map, or a nested object that the flat encoder couldn't flatten because it was already a Y.Map instance).","commonSituations":"Mixing flat-data blocks with code that calls native2Y/Y.Map directly on a nested field; importing data from a non-flat block into a flat one; a transformer writing a nested Y.Map into prop keys; upgrading a block to isFlatData without migrating its stored values.","solutions":["For flat-data blocks, store nested objects as plain JS objects (the flat encoder will flatten them to dotted keys) instead of pre-wrapping in Y.Map.","If you need a nested map, wrap it in Boxed (schema model supports Boxed values) rather than a raw Y.Map.","Migrate existing stored Y.Map values to dotted-flat or Boxed form before opening the doc.","Confirm the block schema's isFlatData flag matches how its props are written."],"exampleFix":"// before: storing a raw nested Y.Map on a flat-data block\nblock.props.style = new Y.Map(); // triggers the error on load\n\n// after: store a plain object (flattened to prop:style.*) or use Boxed\nblock.props.style = { color: '#000', bold: false };\n// or, for an opaque nested map:\nblock.props.advanced = new Boxed(new Y.Map());","handlingStrategy":"validation","validationCode":"import * as Y from 'yjs';\n\nexport function assertNoNestedYMap(values: Iterable<unknown>): void {\n  for (const v of values) {\n    if (v instanceof Y.Map) {\n      throw new Error('flat-data block cannot store a nested Y.Map; use a plain object or Boxed');\n    }\n  }\n}\n\n// before assigning into a flat-data block prop\nassertNoNestedYMap(Object.values(props));\nblock.props = { ...props };","typeGuard":"import * as Y from 'yjs';\nexport const hasNoNestedYMap = (value: unknown): boolean => {\n  if (value instanceof Y.Map) return false;\n  if (value && typeof value === 'object') {\n    return Object.values(value).every(hasNoNestedYMap);\n  }\n  return true;\n};","tryCatchPattern":"try {\n  // trigger flat initialization (e.g. by reading the block proxy)\n  void block.props;\n} catch (e) {\n  if (e instanceof BlockSuiteError && e.code === ErrorCode.ReactiveProxyError && /Y.Map as value of Y.Map/.test(e.message)) {\n    // migrate offending prop to plain object or Boxed, then reload\n    migrateFlatProp(yBlock);\n  } else throw e;\n}","preventionTips":["For flat-data blocks, store nested data as plain JS objects; let the encoder flatten them.","If you need an opaque nested map, wrap it in Boxed, not a raw Y.Map.","Audit transformers/importers writing into flat-data block prop keys.","Confirm isFlatData on the schema matches how props are written."],"tags":["reactive-proxy","flat-data","yjs","schema"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}