{"record":{"id":"4d33e14da490551e","repo":"hcengineering/platform","slug":"attribute-not-found","errorCode":null,"errorMessage":"attribute not found","messagePattern":"attribute not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/view-resources/src/components/ValueSelector.svelte","lineNumber":64,"sourceCode":"      return\n    }\n    progress = true\n    const docs = [...(Array.isArray(value) ? value : [value])]\n\n    const changed = (d: Doc) => (d as any)[attribute] !== newStatus\n    const ops = client.apply('value-selector:' + generateId())\n\n    // We need to sort docs by modified date, to have same modified order impacted.\n    docs.sort((a: Doc, b: Doc) => b._id.localeCompare(a._id))\n\n    for (const it of docs.filter(changed)) {\n      const cl = Hierarchy.mixinOrClass(it)\n      const attr =\n        castRequest !== undefined\n          ? hierarchy.getAttribute(castRequest, attribute)\n          : hierarchy.getAttribute(cl, attribute)\n      if (attr === undefined) {\n        throw new Error('attribute not found')\n      }\n      await updateAttribute(ops, it, cl, { key: attribute, attr }, newStatus)\n    }\n    await ops.commit()\n    progress = false\n    dispatch('close', newStatus)\n  }\n\n  $: current = Array.isArray(value)\n    ? value.every((v) => (v as any)[attribute] === (value as any[])[0][attribute])\n      ? (value as any[])[0][attribute]\n      : value\n    : (value as any)[attribute]\n\n  let finalQuery: DocumentQuery<Doc> = {}\n\n  let docMatch = true\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/plugins/view-resources/src/components/ValueSelector.svelte#L46-L82","documentation":"ValueSelector.svelte's changeValue looks up the attribute being edited on the document's class (or the castRequest mixin) via hierarchy.getAttribute before calling updateAttribute. If the hierarchy has no attribute with that key for the resolved class/mixin, it throws Error('attribute not found'). This is a client-side programming/configuration error: the component was rendered with an `attribute` prop that does not exist on the objects it is bound to.","triggerScenarios":"Rendering ValueSelector with an `attribute` key not defined on the value's class (e.g. typo in the attribute name, attribute only exists on a mixin but castRequest is undefined, or the doc is a subclass lacking the parent's attribute). The lookup happens per doc inside docs.filter(changed), so it fires on the first mismatching doc during a value change.","commonSituations":"Passing a mixin attribute key without setting castRequest to that mixin; mixed selection where Array<Doc> contains docs of different classes and one lacks the attribute; renaming an attribute in the model without updating component call sites; plugin version mismatch between view-resources and the domain plugin defining the class.","solutions":["Check the `attribute` prop spelling against the actual class/mixin model definition for the bound documents.","If the attribute belongs to a mixin, pass castRequest=<Ref<Mixin>> so getAttribute resolves it against the mixin instead of the base class.","Ensure all docs in a multi-selection share the class/mixin that defines the attribute (filter the selection or disable the control otherwise).","Verify the domain plugin defining the class is installed/upgraded so the hierarchy contains the attribute.","Guard before use: call hierarchy.getAttribute yourself and show a disabled state instead of letting changeValue throw."],"exampleFix":"// before\nconst attr = castRequest !== undefined\n  ? hierarchy.getAttribute(castRequest, attribute)\n  : hierarchy.getAttribute(cl, attribute)\nif (attr === undefined) {\n  throw new Error('attribute not found')\n}\n// after\nconst attr = castRequest !== undefined\n  ? hierarchy.getAttribute(castRequest, attribute)\n  : hierarchy.getAttribute(cl, attribute)\nif (attr === undefined) {\n  console.error(`ValueSelector: attribute '${attribute}' not found on ${cl}`, it)\n  dispatch('close', undefined)\n  return\n}","handlingStrategy":"validation","validationCode":"const hierarchy = getClient().getHierarchy()\nconst cl = Hierarchy.mixinOrClass(value)\nconst attr = castRequest !== undefined\n  ? hierarchy.getAttribute(castRequest, attribute)\n  : hierarchy.getAttribute(cl, attribute)\nif (attr === undefined) {\n  // render control as disabled instead of attempting the update\n}","typeGuard":"function hasAttribute (hierarchy: Hierarchy, cl: Ref<Class<Doc>>, attribute: string, castRequest?: Ref<Mixin<Doc>>): boolean {\n  return (castRequest !== undefined\n    ? hierarchy.getAttribute(castRequest, attribute)\n    : hierarchy.getAttribute(cl, attribute)) !== undefined\n}","tryCatchPattern":"try {\n  await changeValue(newValue)\n} catch (err) {\n  if (err.message === 'attribute not found') {\n    console.error(`Attribute '${attribute}' missing on object class`, err)\n    dispatch('close', undefined)\n  } else {\n    throw err\n  }\n}","preventionTips":["Pass castRequest whenever the attribute is defined on a mixin, not the base class.","Validate the attribute prop against the hierarchy at component init and disable the selector if absent.","For multi-selection, ensure all selected docs share the same class/mixin defining the attribute.","Update all ValueSelector call sites when renaming model attributes."],"tags":["hierarchy","attribute-lookup","view-plugin","mixin"],"backgroundTag":"attribute-not-found-in-hierarchy","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}