hcengineering/platform · error · ProcessError
process.error.AttributeNotExists
process.error.AttributeNotExists
Error message
Attribute not exists: {key} What it means
Thrown by getNestedValue when the resolved path (realPath) does not correspond to any attribute on the card's class according to control.client.getHierarchy().findAttribute. The nested context references a path that does not exist on the target object.
Source
Thrown at server-plugins/process-resources/src/utils.ts:135
if (transform === undefined) throw processError(process.error.MethodNotFound, { methodId: func.func }, {}, true)
if (!control.client.getHierarchy().hasMixin(transform, serverProcess.mixin.FuncImpl)) {
throw processError(process.error.MethodNotFound, { methodId: func.func }, {}, true)
}
const funcImpl = control.client.getHierarchy().as(transform, serverProcess.mixin.FuncImpl)
const f = await getResource(funcImpl.func)
value = await f(value, func.props, control, execution)
}
return value
}
async function getNestedValue (control: ProcessControl, execution: Execution, context: SelectedNested): Promise<any> {
const card = control.cache.get(execution.card)
if (card === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.card }, {}, true)
const _process = control.client.getModel().findObject(execution.process)
if (_process === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.process })
const realPath = resolveAttributeId(_process, context.path)
const attr = control.client.getHierarchy().findAttribute(card._class, realPath)
if (attr === undefined) throw processError(process.error.AttributeNotExists, { key: realPath })
const nestedValue = getValue(control, execution, context.path, card)
if (nestedValue === undefined) throw processError(process.error.EmptyAttributeContextValue, {}, { attr: attr.label })
const parentType = attr.type._class === core.class.ArrOf ? (attr.type as ArrOf<Doc>).of : attr.type
const targetClass = parentType._class === core.class.RefTo ? (parentType as RefTo<Doc>).to : parentType._class
const refs = Array.isArray(nestedValue) ? nestedValue : [nestedValue]
const target = await control.client.findAll(targetClass, {
_id: { $in: refs }
})
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)View on GitHub (pinned to 63e28dc964)
Solutions
- Check context.path resolves to a real attribute on the card's class (inspect hierarchy.findAttribute result).
- Update the process template's nested path after schema renames/migrations.
- Apply the required mixin to the card's class if the attribute is mixin-provided.
- Validate paths against the hierarchy at template design/save time.
Example fix
// before: blind nested access
path: 'customField.oldName'
// after: verify attribute exists
const attr = control.client.getHierarchy().findAttribute(card._class, resolveAttributeId(_process, 'customField.oldName'))
if (attr === undefined) throw new Error('Path not found on ' + card._class) Defensive patterns
Strategy: validation
Validate before calling
const realPath = resolveAttributeId(_process, context.path)
if (control.client.getHierarchy().findAttribute(card._class, realPath) === undefined) {
throw new Error(`Attribute ${realPath} does not exist on ${card._class}`)
} Type guard
function attributeExists(hierarchy: Hierarchy, _class: Ref<Class<Doc>>, key: string): boolean {
return hierarchy.findAttribute(_class, key) !== undefined
} Try / catch
try {
const value = await getNestedValue(control, execution, ctx)
} catch (err) {
if ((err as Error).message.startsWith('Attribute not exists')) {
// correct the path in the template
} else throw err
} Prevention
- Validate nested paths against the hierarchy when saving templates
- Update templates after attribute renames/migrations
- Ensure mixin-provided attributes are available on the card class
- Test templates against the target schema before deployment
When it happens
Trigger: getContextValue → getNestedValue where context.path (after resolveAttributeId mapping against the process) yields a key not present in the hierarchy for card._class — renamed attributes, wrong class, or missing mixin providing the attribute.
Common situations: Process templates written against an older schema; attributes moved into mixins that are not applied to the card's class; typos in nested paths; platform version changes renaming attributes.
Related errors
- Failed to deserialize as StandardPatchOperation: {}. Also fa
- process.error.RequiredParamsNotProvided
- process.error.ObjectNotFound
- process.error.ObjectNotFound
- process.error.EmptyAttributeContextValue
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/fc1683e677fa0561.
Report an issue: GitHub.