{"record":{"id":"b8799bfa46e660ed","repo":"toeverything/AFFiNE","slug":"valuenotexists-b8799b","errorCode":"ValueNotExists","errorMessage":"Failed to create portal root","messagePattern":"Failed to create portal root","errorType":"exception","errorClass":"BlockSuiteError","httpStatus":null,"severity":"error","filePath":"blocksuite/affine/components/src/portal/helper.ts","lineNumber":44,"sourceCode":"  identifyWrapper = true,\n}: PortalOptions) {\n  const portalRoot = document.createElement('div');\n  if (identifyWrapper) {\n    portalRoot.classList.add('blocksuite-portal');\n  }\n  if (shadowDom) {\n    portalRoot.attachShadow({\n      mode: 'open',\n      ...(typeof shadowDom !== 'boolean' ? shadowDom : {}),\n    });\n  }\n  signal.addEventListener('abort', () => {\n    portalRoot.remove();\n  });\n\n  const root = shadowDom ? portalRoot.shadowRoot : portalRoot;\n  if (!root) {\n    throw new BlockSuiteError(\n      BlockSuiteError.ErrorCode.ValueNotExists,\n      'Failed to create portal root'\n    );\n  }\n\n  let updateId = 0;\n  const updatePortal: (id: number) => void = id => {\n    if (id !== updateId) {\n      console.warn(\n        'Potentially infinite recursion! Please clean up the old event listeners before `updatePortal`'\n      );\n      return;\n    }\n    updateId++;\n    const curId = updateId;\n    const templateResult =\n      template instanceof Function\n        ? template({ updatePortal: () => updatePortal(curId) })","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/blocksuite/affine/components/src/portal/helper.ts#L26-L62","documentation":"For non-document tables the validator strictly rejects any data key that is not declared in table.schema — persisting undeclared fields would silently diverge from the persisted shape, and the adapters only store what the schema knows. Document tables (isDocumentTable) are exempt because they accept open shapes; regular tables fail with the offending key named.","triggerScenarios":"Inserting { id, name, tempFlag } when tempFlag was never added to the schema; renaming a field in code but not in the schema; computed/derived properties left on the object before insert; spreading a DTO (with transport-only fields) directly as entity data.","commonSituations":"Schema migration added the field to TypeScript types but not the table definition; reusing API DTOs as entities; newer client writing to an older schema.","solutions":["Add the field to the table schema if it should be persisted","Otherwise strip undeclared keys before the write: keep only Object.keys(table.schema)","If open shapes are intended, use a document table instead of a regular table"],"exampleFix":"// before\ntable.insert({ data: { id: 'a1', name: 'x', tempFlag: true } }); // tempFlag not in schema\n\n// after\n// option A: persist it -> add to schema: tempFlag: { type: 'boolean' }\n// option B: strip before write:\nconst data = Object.fromEntries(\n  Object.entries(entity).filter(([k]) => k in table.schema)\n);\ntable.insert({ data });","handlingStrategy":"validation","validationCode":"function pickSchemaFields(data: Record<string, any>, schema: Record<string, unknown>) {\n  return Object.fromEntries(Object.entries(data).filter(([key]) => key in schema));\n}\n\ntable.insert({ data: pickSchemaFields(entity, table.schema) });","typeGuard":"null","tryCatchPattern":null,"preventionTips":["Do not reuse DTOs as entities — strip transport-only fields before writing","When adding a field to TypeScript types, add it to the table schema in the same change","Use a document table when open shapes are intended; regular tables enforce closed schemas"],"tags":["orm","database","schema-validation","unknown-field"],"backgroundTag":"unknown-schema-field","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}