{"record":{"id":"0936629bb294a7c3","repo":"siyuan-note/siyuan","slug":"the-range-must-be-inside-one-editable-source-block","errorCode":null,"errorMessage":"The range must be inside one editable source block of this Protyle instance","messagePattern":"The range must be inside one editable source block of this Protyle instance","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"app/src/protyle/util/trackedRange.ts","lineNumber":1147,"sourceCode":"};\n\nexport const trackRange = (protyle: IProtyle, range: Range,\n                           options: ITrackRangeOptions): ITrackedRangeHandle => {\n    if (destroyedProtyles.has(protyle)) {\n        throw new Error(\"Cannot track a range in a destroyed Protyle instance\");\n    }\n    if (!options?.owner || ![\"function\", \"object\"].includes(typeof options.owner)) {\n        throw new TypeError(\"The tracked range owner is required\");\n    }\n    if (options.affinity && ![\"after\", \"before\"].includes(options.affinity)) {\n        throw new TypeError(\"The tracked range affinity must be before or after\");\n    }\n    if (unloadingPlugins.has(options.owner)) {\n        throw new Error(\"Cannot track a range for an unloaded plugin\");\n    }\n    const rangeSnapshot = getRangeSnapshot(protyle, range);\n    if (!rangeSnapshot) {\n        throw new TypeError(\"The range must be inside one editable source block of this Protyle instance\");\n    }\n    const targetTokens = rangeSnapshot.stream.tokens.slice(rangeSnapshot.start, rangeSnapshot.end);\n    if (!range.collapsed && targetTokens.length === 0) {\n        throw new TypeError(\"The tracked range must contain semantic content\");\n    }\n    const handle = Object.freeze({id: `tracked-range-${++handleSequence}`});\n    const trackedRange = range.cloneRange();\n    const state: ITrackedRangeState = {\n        range: trackedRange,\n        startContainer: trackedRange.startContainer,\n        endContainer: trackedRange.endContainer,\n        exactTarget: getExactlySelectedElement(trackedRange),\n        collapsed: trackedRange.collapsed,\n        affinity: options.affinity || \"before\",\n        targetTokens,\n        tokens: rangeSnapshot.stream.tokens,\n        start: rangeSnapshot.start,\n        end: rangeSnapshot.end,","sourceCodeStart":1129,"sourceCodeEnd":1165,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/app/src/protyle/util/trackedRange.ts#L1129-L1165","documentation":"trackRange precondition: the given DOM Range does not lie entirely inside a single editable source block of the passed Protyle instance. Range tracking is per editable block, so a range spanning blocks, in a different editor, or outside editable content is rejected.","triggerScenarios":"Thrown at app/src/protyle/util/trackedRange.ts:1147 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Narrow the range to one editable block element before tracking","Verify the range was obtained from the same Protyle instance","Re-create the range from saved anchor offsets inside one block"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}