hcengineering/platform · error · PlatformError

core.status.ObjectNotFound

core.status.ObjectNotFound

Error message

ObjectNotFound

What it means

setObjectValue builds nested intermediate objects when applying a dotted-path update. When the path traverses an array (dots present) it cannot safely create nested values inside arrays, so it throws a PlatformError with core.status.ObjectNotFound and _id:'dots' to signal 'arrays are not supported' for this update path.

Source

Thrown at foundations/core/packages/core/src/objvalue.ts:53

 */
export function setObjectValue (key: string, doc: Doc, newValue: any): void {
  // Check dot notation
  if (key.length === 0) {
    return
  }
  key = key.split('\\$').join('$')
  let dots = key.split('.')
  // Replace escapting, since memdb is not escape keys

  const last = dots[dots.length - 1]
  dots = dots.slice(0, -1)

  // We have dots, so iterate in depth
  let value = doc as any
  for (const d of dots) {
    if (Array.isArray(value) && isNestedArrayQuery(value, d)) {
      // Arrays are not supported
      throw new PlatformError(new Status(Severity.ERROR, core.status.ObjectNotFound, { _id: 'dots' }))
    }
    const lvalue = value?.[d]
    if (lvalue === undefined) {
      value[d] = {}
      value = value?.[d]
    } else {
      value = lvalue
    }
  }
  value[last] = clone(newValue)
  return value
}

function isNestedArrayQuery (value: any, d: string): boolean {
  return Number.isNaN(Number.parseInt(d)) && value?.[d as any] === undefined
}

function getNestedArrayValue (value: any[], name: string): any[] {

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Restructure the update to replace the whole array field instead of addressing elements by dotted path
  2. Load the doc, mutate the array in code, and update via a non-dotted patch
  3. Change the data model so the nested collection is a separate AttachedDoc rather than an embedded array
  4. Catch this status code and surface a clear 'array updates not supported' message

Example fix

// before
await applyUpdate(doc._id, doc._class, { 'items.0.done': true })
// after
const items = (doc.items ?? []).map((it, i) => i === 0 ? { ...it, done: true } : it)
await applyUpdate(doc._id, doc._class, { items })
Defensive patterns

Strategy: validation

Validate before calling

const key = 'items.0.done'
const root = key.split('.')[0]
const probe = (doc as any)[root]
if (Array.isArray(probe)) {
  throw new Error(`Dotted update '${key}' targets an array; replace the whole field instead`)
}
await applyUpdate(doc._id, doc._class, { [key]: value })

Try / catch

try {
  await applyUpdate(_id, _class, patch)
} catch (err: any) {
  if (err?.status?.code === core.status.ObjectNotFound && err?.status?.params?._id === 'dots') {
    // array update rejected - fallback to whole-field replacement
    return applyWholeFieldUpdate(_id, _class, patch)
  }
  throw err
}

Prevention

When it happens

Trigger: Calling setObjectValue (via applyUpdate or updateMixin4Doc) with a patch key containing dots that resolves into an array element, e.g. 'items.0.name' or 'tags.x' where tags is an array and isNestedArrayQuery matches.

Common situations: UI forms generating dotted paths over array fields; migrating updates written for a plain object schema while the attribute was changed to an array; mixin updates addressing array-of-objects properties.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/4ba719c6426761d3. Report an issue: GitHub.