{"record":{"id":"fc1683e677fa0561","repo":"hcengineering/platform","slug":"process-error-attributenotexists","errorCode":"process.error.AttributeNotExists","errorMessage":"Attribute not exists: {key}","messagePattern":"Attribute not exists: (.+?)","errorType":"exception","errorClass":"ProcessError","httpStatus":null,"severity":"error","filePath":"server-plugins/process-resources/src/utils.ts","lineNumber":135,"sourceCode":"    if (transform === undefined) throw processError(process.error.MethodNotFound, { methodId: func.func }, {}, true)\n    if (!control.client.getHierarchy().hasMixin(transform, serverProcess.mixin.FuncImpl)) {\n      throw processError(process.error.MethodNotFound, { methodId: func.func }, {}, true)\n    }\n    const funcImpl = control.client.getHierarchy().as(transform, serverProcess.mixin.FuncImpl)\n    const f = await getResource(funcImpl.func)\n    value = await f(value, func.props, control, execution)\n  }\n  return value\n}\n\nasync function getNestedValue (control: ProcessControl, execution: Execution, context: SelectedNested): Promise<any> {\n  const card = control.cache.get(execution.card)\n  if (card === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.card }, {}, true)\n  const _process = control.client.getModel().findObject(execution.process)\n  if (_process === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.process })\n  const realPath = resolveAttributeId(_process, context.path)\n  const attr = control.client.getHierarchy().findAttribute(card._class, realPath)\n  if (attr === undefined) throw processError(process.error.AttributeNotExists, { key: realPath })\n  const nestedValue = getValue(control, execution, context.path, card)\n  if (nestedValue === undefined) throw processError(process.error.EmptyAttributeContextValue, {}, { attr: attr.label })\n  const parentType = attr.type._class === core.class.ArrOf ? (attr.type as ArrOf<Doc>).of : attr.type\n  const targetClass = parentType._class === core.class.RefTo ? (parentType as RefTo<Doc>).to : parentType._class\n  const refs = Array.isArray(nestedValue) ? nestedValue : [nestedValue]\n  const target = await control.client.findAll(targetClass, {\n    _id: { $in: refs }\n  })\n  if (target.length === 0) throw processError(process.error.RelatedObjectNotFound, {}, { attr: attr.label })\n  const realKey = resolveAttributeId(_process, context.key)\n  const nested = control.client.getHierarchy().findAttribute(targetClass, realKey)\n  if (context.sourceFunction !== undefined) {\n    const transform = control.client.getModel().findObject(context.sourceFunction.func)\n    if (transform === undefined) {\n      throw processError(process.error.MethodNotFound, { methodId: context.sourceFunction.func }, {}, true)\n    }\n    if (!control.client.getHierarchy().hasMixin(transform, serverProcess.mixin.FuncImpl)) {\n      throw processError(process.error.MethodNotFound, { methodId: context.sourceFunction.func }, {}, true)","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server-plugins/process-resources/src/utils.ts#L117-L153","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: blind nested access\npath: 'customField.oldName'\n// after: verify attribute exists\nconst attr = control.client.getHierarchy().findAttribute(card._class, resolveAttributeId(_process, 'customField.oldName'))\nif (attr === undefined) throw new Error('Path not found on ' + card._class)","handlingStrategy":"validation","validationCode":"const realPath = resolveAttributeId(_process, context.path)\nif (control.client.getHierarchy().findAttribute(card._class, realPath) === undefined) {\n  throw new Error(`Attribute ${realPath} does not exist on ${card._class}`)\n}","typeGuard":"function attributeExists(hierarchy: Hierarchy, _class: Ref<Class<Doc>>, key: string): boolean {\n  return hierarchy.findAttribute(_class, key) !== undefined\n}","tryCatchPattern":"try {\n  const value = await getNestedValue(control, execution, ctx)\n} catch (err) {\n  if ((err as Error).message.startsWith('Attribute not exists')) {\n    // correct the path in the template\n  } else throw err\n}","preventionTips":["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"],"tags":["process","schema","attribute-missing"],"backgroundTag":"attribute-not-exists","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}