{"record":{"id":"32d438bf57ff9af3","repo":"siyuan-note/siyuan","slug":"the-tracked-range-must-contain-semantic-content","errorCode":null,"errorMessage":"The tracked range must contain semantic content","messagePattern":"The tracked range must contain semantic content","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"app/src/protyle/util/trackedRange.ts","lineNumber":1151,"sourceCode":"    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,\n        sourceBlockID: rangeSnapshot.snapshot.block.getAttribute(\"data-node-id\") || \"\",\n        sourceAncestorIDs: getAncestorBlockIDs(protyle.wysiwyg.element, rangeSnapshot.snapshot.block),\n        rootIDs: rangeSnapshot.stream.roots.map(root => root.getAttribute(\"data-node-id\") || \"\").filter(Boolean),\n        rootBlockIDs: getRootBlockIDs(rangeSnapshot.stream.roots),","sourceCodeStart":1133,"sourceCodeEnd":1169,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/app/src/protyle/util/trackedRange.ts#L1133-L1169","documentation":"trackRange precondition: the range to track contains no semantic content (e.g. an empty selection or only whitespace/formatting). Nothing meaningful would survive edit tracking, so the request is refused.","triggerScenarios":"Thrown at app/src/protyle/util/trackedRange.ts:1151 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Only track ranges with a non-empty selection","Expand the selection to include the intended text node","Skip tracking for caret-only positions"],"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"}