ianstormtaylor/slate · error · Error

A HyperscriptRangeRef must be passed as the ref prop of a <f

Error message

A HyperscriptRangeRef must be passed as the ref prop of a <focus /> tag that is used inside an <editor>.

What it means

In slate-hyperscript, a <focus ref={...}/> tag's ref stores the focus Point only when rendered inside an <editor> element. The range() method on HyperscriptRangeRef throws this error when the focus Point is missing — the anchor was captured but the focus never was, because the <focus/> tag was outside an editor, missing entirely, or attached to a different ref. A Slate Range requires both endpoints.

Source

Thrown at packages/slate-hyperscript/src/refs.ts:44

 * Hyperscript range refs can be used to construct arbitrary range using the ref
 * props of <anchor /> and <focus /> tags.
 */

export class HyperscriptRangeRef {
  anchor?: Point
  focus?: Point

  range(): Range {
    const { anchor, focus } = this

    if (anchor == null) {
      throw new Error(
        'A HyperscriptRangeRef must be passed as the ref prop of an <anchor /> tag that is used inside an <editor>.'
      )
    }

    if (focus == null) {
      throw new Error(
        'A HyperscriptRangeRef must be passed as the ref prop of a <focus /> tag that is used inside an <editor>.'
      )
    }

    return { anchor, focus }
  }
}

View on GitHub (pinned to 72a37c701e)

Solutions

  1. Ensure a <focus ref={r}/> tag exists inside the same <editor> as the <anchor ref={r}/> tag
  2. Check that anchor and focus use the same ref object when you intend to call range() on it
  3. If you only need a single point, call .point() on a point ref instead of range()

Example fix

// before
<editor>
  <anchor ref={r} />
  <text>a</text>
</editor>
// no <focus ref={r}/> anywhere
r.current.range() // throws

// after
<editor>
  <anchor ref={r} />
  <text>a</text>
  <focus ref={r} />
</editor>
r.current.range() // works
Defensive patterns

Strategy: validation

Validate before calling

const r = focusRef.current
if (r?.anchor != null && r?.focus != null) {
  const range = r.range()
}

Type guard

const hasRange = (r) =>
  r != null && r.anchor != null && r.focus != null

Prevention

When it happens

Trigger: Using <anchor ref={r}/> inside an <editor> but placing <focus ref={r}/> in a fragment; omitting the <focus/> tag while still calling range(); passing a second ref to <focus/> so the first ref has an anchor but no focus.

Common situations: Copy-paste test markup where the focus tag landed outside the editor; using two different refs and calling range() on only one; refactoring selection tests.

Related errors


AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27). Data as JSON: /api/errors/d5af83c4e7c3b1a9. Report an issue: GitHub.