siyuan-note/siyuan · error · TypeError

The tracked range must contain semantic content

Error message

The tracked range must contain semantic content

What it means

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.

Source

Thrown at app/src/protyle/util/trackedRange.ts:1151

    if (destroyedProtyles.has(protyle)) {
        throw new Error("Cannot track a range in a destroyed Protyle instance");
    }
    if (!options?.owner || !["function", "object"].includes(typeof options.owner)) {
        throw new TypeError("The tracked range owner is required");
    }
    if (options.affinity && !["after", "before"].includes(options.affinity)) {
        throw new TypeError("The tracked range affinity must be before or after");
    }
    if (unloadingPlugins.has(options.owner)) {
        throw new Error("Cannot track a range for an unloaded plugin");
    }
    const rangeSnapshot = getRangeSnapshot(protyle, range);
    if (!rangeSnapshot) {
        throw new TypeError("The range must be inside one editable source block of this Protyle instance");
    }
    const targetTokens = rangeSnapshot.stream.tokens.slice(rangeSnapshot.start, rangeSnapshot.end);
    if (!range.collapsed && targetTokens.length === 0) {
        throw new TypeError("The tracked range must contain semantic content");
    }
    const handle = Object.freeze({id: `tracked-range-${++handleSequence}`});
    const trackedRange = range.cloneRange();
    const state: ITrackedRangeState = {
        range: trackedRange,
        startContainer: trackedRange.startContainer,
        endContainer: trackedRange.endContainer,
        exactTarget: getExactlySelectedElement(trackedRange),
        collapsed: trackedRange.collapsed,
        affinity: options.affinity || "before",
        targetTokens,
        tokens: rangeSnapshot.stream.tokens,
        start: rangeSnapshot.start,
        end: rangeSnapshot.end,
        sourceBlockID: rangeSnapshot.snapshot.block.getAttribute("data-node-id") || "",
        sourceAncestorIDs: getAncestorBlockIDs(protyle.wysiwyg.element, rangeSnapshot.snapshot.block),
        rootIDs: rangeSnapshot.stream.roots.map(root => root.getAttribute("data-node-id") || "").filter(Boolean),
        rootBlockIDs: getRootBlockIDs(rangeSnapshot.stream.roots),

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Only track ranges with a non-empty selection
  2. Expand the selection to include the intended text node
  3. Skip tracking for caret-only positions
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at app/src/protyle/util/trackedRange.ts:1151 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/32d438bf57ff9af3. Report an issue: GitHub.