{"record":{"id":"588617aa5bb14128","repo":"hcengineering/platform","slug":"attribute-presenter-not-found-for-json-stringify","errorCode":null,"errorMessage":"attribute presenter not found for ${JSON.stringify(preserveKey)}","messagePattern":"attribute presenter not found for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/view-resources/src/utils.ts","lineNumber":376,"sourceCode":"export async function getAttributePresenter (\n  client: Client,\n  _class: Ref<Class<Obj>>,\n  key: string,\n  preserveKey: BuildModelKey,\n  mixinClass?: Ref<Mixin<CollectionPresenter>>,\n  _category?: AttributeCategory\n): Promise<AttributeModel> {\n  const actualMixinClass = mixinClass ?? view.mixin.AttributePresenter\n  const hierarchy = client.getHierarchy()\n  const attribute = hierarchy.getAttribute(_class, key)\n  let { attrClass, category } = getAttributePresenterClass(hierarchy, attribute.type)\n  if (_category !== undefined) {\n    category = _category\n  }\n\n  const presenterRef = findAttributePresenter(client, _class, key, actualMixinClass, category)\n  if (presenterRef === undefined) {\n    throw new Error('attribute presenter not found for ' + JSON.stringify(preserveKey))\n  }\n\n  const isCollectionAttr = category === 'collection'\n\n  const mixin = isCollectionAttr ? view.mixin.CollectionPresenter : actualMixinClass\n\n  let presenterMixin: AttributePresenter | CollectionPresenter | undefined = hierarchy.classHierarchyMixin(\n    attrClass,\n    mixin\n  )\n\n  if (presenterMixin?.presenter === undefined && mixinClass != null && mixin === mixinClass) {\n    presenterMixin = hierarchy.classHierarchyMixin(attrClass, view.mixin.AttributePresenter)\n  }\n\n  const resultKey = preserveKey.sortingKey ?? preserveKey.key\n  const sortingKey = Array.isArray(resultKey)\n    ? resultKey","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/plugins/view-resources/src/utils.ts#L358-L394","documentation":"getAttributePresenter resolves a presenter function for a class/key combination via findAttributePresenter and throws when none is registered. Presenters are how the UI renders attribute values; an unregistered presenter means the framework does not know how to display that attribute. The preserveKey in the message identifies exactly which key failed.","triggerScenarios":"Rendering a component with a key (_class + key, possibly mixin class or category like 'collection') for which no presenter was registered, including built-in types missing from the presenter map.","commonSituations":"Custom data types without a registered presenter; typos in keys; plugin providing the presenter not loaded; new attribute types added after a version upgrade where the old presenter map lacks them; rendering collection attributes without a CollectionPresenter.","solutions":["Register a presenter for the attribute's type/class (addPresenter for the type class or mixin).","Check the key and mixin class passed to getAttributePresenter for typos.","Ensure the plugin that contributes the presenter is included in the build/assembly.","Fall back to a default text presenter for unknown types."],"exampleFix":"// before\nconst presenter = getPresenter(client, myClass, 'customField')\n// after\naddPresenter(myTypeClass, plugin.component.TextPresenter) // register first\nconst presenter = getAttributePresenterSafe(client, myClass, 'customField') ?? textPresenter","handlingStrategy":"fallback","validationCode":"import { getAttributePresenterSafe } from '@hcengineering/view-resources'\nconst presenter = getAttributePresenterSafe(client, _class, key) ?? defaultTextPresenter","typeGuard":"function hasPresenter(h: Hierarchy, cls: Ref<Class<Doc>>, key: string): boolean { return findAttributePresenter(client, cls, key) !== undefined }","tryCatchPattern":"try { return await getAttributePresenter(client, _class, key) } catch { return textPresenter }","preventionTips":["Register presenters for every custom type/mixin","Prefer getAttributePresenterSafe for optional rendering","Keep presenter-providing plugins in the assembly","Test rendering of all model attributes"],"tags":["presenter","configuration","ui","view-model"],"backgroundTag":"missing-presenter-registration","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}