hcengineering/platform · error · ProcessError

process.error.EmptyRelatedObjectValue

process.error.EmptyRelatedObjectValue

Error message

Empty related object {parent} value: {attr}

What it means

The source function executed successfully but the computed value for the requested nested attribute was null/undefined. The library requires context values to be non-empty, so it throws EmptyRelatedObjectValue with the parent attribute label and the nested attribute (or embedded key).

Source

Thrown at server-plugins/process-resources/src/utils.ts:162

  if (target.length === 0) throw processError(process.error.RelatedObjectNotFound, {}, { attr: attr.label })
  const realKey = resolveAttributeId(_process, context.key)
  const nested = control.client.getHierarchy().findAttribute(targetClass, realKey)
  if (context.sourceFunction !== undefined) {
    const transform = control.client.getModel().findObject(context.sourceFunction.func)
    if (transform === undefined) {
      throw processError(process.error.MethodNotFound, { methodId: context.sourceFunction.func }, {}, true)
    }
    if (!control.client.getHierarchy().hasMixin(transform, serverProcess.mixin.FuncImpl)) {
      throw processError(process.error.MethodNotFound, { methodId: context.sourceFunction.func }, {}, true)
    }
    const funcImpl = control.client.getHierarchy().as(transform, serverProcess.mixin.FuncImpl)
    const f = await getResource(funcImpl.func)
    const reduced = await f(target, {}, control, execution)
    const val = Array.isArray(reduced)
      ? reduced.map((v) => getValue(control, execution, context.key, v))
      : getValue(control, execution, context.key, reduced)
    if (val == null) {
      throw processError(
        process.error.EmptyRelatedObjectValue,
        {},
        { parent: attr.label, attr: nested?.label ?? getEmbeddedLabel(context.key) }
      )
    }
    return val
  }
  const val = Array.isArray(nestedValue)
    ? target.map((v) => getValue(control, execution, context.key, v))
    : getValue(control, execution, context.key, target[0])
  if (val == null) {
    throw processError(
      process.error.EmptyRelatedObjectValue,
      {},
      { parent: attr.label, attr: nested?.label ?? getEmbeddedLabel(context.key) }
    )
  }
  return val

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Check that the objects returned by the source function actually contain context.key and that the key is correct
  2. Make the transform return a sensible default instead of null for missing keys
  3. Guard the process template so the attribute is optional or provide a fallback value
  4. Fix data so the related objects are fully populated

Example fix

// before
const reduced = await f(target, {}, control, execution) // objects lack 'total'
// after
// in the source function
return items.map((i) => ({ ...i, total: i.total ?? 0 }))
Defensive patterns

Strategy: fallback

Validate before calling

const probe = await f(target, {}, control, execution)
const probeVal = Array.isArray(probe) ? probe.map((v) => v?.[ctx.key]) : probe?.[ctx.key]
if (probeVal == null || probeVal.every((v) => v == null)) throw new Error('Transform yields empty value')

Type guard

function hasValue(v: unknown): v is NonNullable<unknown> {
  return v != null
}

Try / catch

try {
  val = await getContextValue(control, execution, ctx)
} catch (err) {
  if ((err as any)?.code === 'process.error.EmptyRelatedObjectValue') val = defaultValue
  else throw err
}

Prevention

When it happens

Trigger: getContextValue -> getNestedValue: after running the sourceFunction transform and mapping getValue over the result, the resulting val is null (attribute missing on the transformed objects or transform returns nothing).

Common situations: Transform function returns objects without the requested key; optional/nested key path resolves to undefined on real data; misconfigured context.key that does not exist on the transform output.

Related errors


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