{"record":{"id":"8a25dc032a5302a5","repo":"hcengineering/platform","slug":"process-error-emptyattributecontextvalue","errorCode":"process.error.EmptyAttributeContextValue","errorMessage":"Empty attribute value: {attr}","messagePattern":"Empty attribute value: (.+?)","errorType":"exception","errorClass":"ProcessError","httpStatus":null,"severity":"warning","filePath":"server-plugins/process-resources/src/utils.ts","lineNumber":97,"sourceCode":"  const hierarchy = control.client.getHierarchy()\n  const _process = control.client.getModel().findObject(execution.process)\n  if (_process === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.process })\n  const realKey = resolveAttributeId(_process, rawKey)\n  const key = checkMixinKey(realKey, _process.masterTag, hierarchy)\n  return getObjectValue(key, card)\n}\n\nfunction getConstValue (control: ProcessControl, execution: Execution, context: SelectedConst): any {\n  return context.value\n}\n\nfunction getAttributeValue (control: ProcessControl, execution: Execution, context: SelectedContext): any {\n  const card = control.cache.get(execution.card)\n  if (card !== undefined) {\n    const val = getValue(control, execution, context.key, card)\n    if (val == null) {\n      const attr = control.client.getHierarchy().findAttribute(card._class, context.key)\n      throw processError(\n        process.error.EmptyAttributeContextValue,\n        {},\n        { attr: attr?.label ?? getEmbeddedLabel(context.key) }\n      )\n    }\n    return val\n  } else {\n    throw processError(process.error.ObjectNotFound, { _id: execution.card }, {}, true)\n  }\n}\n\nasync function fillValue (\n  value: any,\n  context: SelectedContext,\n  control: ProcessControl,\n  execution: Execution\n): Promise<any> {\n  for (const func of context.functions ?? []) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server-plugins/process-resources/src/utils.ts#L79-L115","documentation":"Thrown by getAttributeValue when the attribute value resolved from the card for a context key is null or undefined. The error message includes the human-readable attribute label (or embedded label) so the user knows which attribute was empty.","triggerScenarios":"getContextValue resolves a SelectedContext whose card is cached but whose attribute (context.key, resolved against the process) is null/undefined on the card — e.g. an unfilled required field, a not-yet-computed value, or a wrong key pointing at an empty attribute.","commonSituations":"Process templates referencing attributes that users haven't filled in; attributes whose values are only set later in the process; typos or renamed attributes yielding empty lookups; optional reference fields left blank.","solutions":["Check the card and ensure the attribute (by context.key) has a value before triggering the context value resolution.","Set a default/initial value for the attribute in the process template or on card creation.","Verify context.key resolves to the intended attribute (check resolveAttributeId / mixin key mapping) in case the key is wrong.","Add a client-side null/undefined check and handle the empty case (prompt user, skip action) instead of calling into the plugin."],"exampleFix":"// before\nconst value = await getContextValue(ctx, control, execution)\n// after: guard empty value before use\nconst card = control.cache.get(execution.card)\nconst value = card != null ? getValue(control, execution, 'Status', card) : undefined\nif (value == null) value = await promptUserFor('Status')","handlingStrategy":"validation","validationCode":"const card = control.cache.get(execution.card)\nconst attr = control.client.getHierarchy().findAttribute(card?._class, context.key)\nconst value = card != null ? (card as any)[context.key] : undefined\nif (value == null) throw new Error(`Attribute ${attr?.label ?? context.key} is empty`)","typeGuard":"function hasValue<T extends Doc>(card: T | undefined, key: string): card is T & Record<string, unknown> {\n  return card !== undefined && (card as any)[key] != null\n}","tryCatchPattern":"try {\n  const value = await getContextValue(ctx, control, execution)\n} catch (err) {\n  if ((err as Error).message.startsWith('Empty attribute value')) {\n    // prompt user or substitute default\n  } else throw err\n}","preventionTips":["Set defaults for attributes used in process contexts","Make context-referenced attributes required in the schema","Check attribute values before triggering dependent process steps","Verify context.key resolves to the intended attribute"],"tags":["process","empty-value","attribute"],"backgroundTag":"empty-attribute-value","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}