overleaf/overleaf · error

Referenced element not a number

Error message

Referenced element not a number

What it means

For 'na' (number add) components, the json type verifies the target element is of type number before applying the increment. If the value at elem[key] is a string, null, boolean, or undefined, applying would silently corrupt the document, so it throws instead.

Source

Thrown at services/document-updater/app/js/sharejs/types/json.js:110

      let parentkey = null
      let elem = container
      let key = 'data'

      for (const p of Array.from(c.p)) {
        parent = elem
        parentkey = key
        elem = elem[key]
        key = p

        if (parent == null) {
          throw new Error('Path invalid')
        }
      }

      if (c.na !== undefined) {
        // Number add
        if (typeof elem[key] !== 'number') {
          throw new Error('Referenced element not a number')
        }
        elem[key] += c.na
      } else if (c.si !== undefined) {
        // String insert
        if (typeof elem !== 'string') {
          throw new Error(
            `Referenced element not a string (it was ${JSON.stringify(elem)})`
          )
        }
        parent[parentkey] = elem.slice(0, key) + c.si + elem.slice(key)
      } else if (c.sd !== undefined) {
        // String delete
        if (typeof elem !== 'string') {
          throw new Error('Referenced element not a string')
        }
        if (elem.slice(key, key + c.sd.length) !== c.sd) {
          throw new Error('Deleted string does not match')
        }

View on GitHub (pinned to 28ad3b03b7)

Solutions

  1. Initialize numeric fields to 0 before any na op runs
  2. Coerce or fix the field to a number first (submit an oi op setting a number), then use na
  3. Validate client-side that snapshot value at the path is typeof 'number' before submitting na
  4. Ensure all writers treat the field strictly as a number

Example fix

// before
doc.at(['views']).increment(1) // views === null
// after
if (typeof doc.get().views !== 'number') doc.at(['views']).set(0)
doc.at(['views']).increment(1)
Defensive patterns

Strategy: type-guard

Validate before calling

const v = doc.get().views // resolve path to target
if (typeof v !== 'number') throw new Error(`views is not a number: ${typeof v}`)

Type guard

const isNumber = (v) => typeof v === 'number' && !Number.isNaN(v)

Try / catch

try {
  doc.at(['views']).increment(1)
} catch (err) {
  if (err.message === 'Referenced element not a number') {
    doc.at(['views']).set(0)
    doc.at(['views']).increment(1)
    return
  }
  throw err
}

Prevention

When it happens

Trigger: Submitting na against a field holding a non-number — e.g. counter initialized to null or '0' (string), or the field was never created so it is undefined; another client replaced the counter with a string.

Common situations: Counters initialized from user/config input as strings; missing field on first use (undefined); a migration that changed the counter to a different type.

Related errors


AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03). Data as JSON: /api/errors/45c8bb71cd89ac27. Report an issue: GitHub.