hcengineering/platform · error
object presenter not found for class=${_class}, preserve key
Error message
object presenter not found for class=${_class}, preserve key ${JSON.stringify(preserveKey)} What it means
getPresenter falls back to getObjectPresenter to render a whole object when the key resolves to an empty key (an object-level presenter, e.g. for a lookup reference cell). It throws when no object presenter is registered for the given class. Like the attribute-presenter error, it signals a missing UI registration for that class.
Source
Thrown at plugins/view-resources/src/utils.ts:464
): Promise<AttributeModel> {
if (key.presenter !== undefined) {
const { presenter, label, sortingKey } = key
return {
key: key.key ?? '',
sortingKey: sortingKey ?? '',
_class,
label: label as IntlString,
presenter: typeof presenter === 'string' ? await getResource(presenter) : presenter,
props: preserveKey.props,
displayProps: preserveKey.displayProps,
collectionAttr: isCollectionAttr,
isLookup: false
}
}
if (key.key.length === 0) {
const p = await getObjectPresenter(client, _class, preserveKey, isCollectionAttr)
if (p === undefined) {
throw new Error(`object presenter not found for class=${_class}, preserve key ${JSON.stringify(preserveKey)}`)
}
return p
} else {
if (key.key.startsWith('$lookup')) {
if (lookup === undefined) {
throw new Error(`lookup class does not provided for ${key.key}`)
}
return await getLookupPresenter(client, _class, key, preserveKey, lookup)
}
return await getAttributePresenter(client, _class, key.key, preserveKey, undefined, _category)
}
}
function getKeyLookup<T extends Doc> (
hierarchy: Hierarchy,
_class: Ref<Class<T>>,
key: string,
lookup: Lookup<T>,View on GitHub (pinned to 63e28dc964)
Solutions
- Register a default object presenter for the class (view.component.ObjectPresenter per-class registration).
- Verify the class id and preserveKey; ensure the lookup provides the correct lookup class.
- Ensure the contributing plugin is installed/loaded.
- Provide an explicit presenter/component for the cell instead of relying on defaults.
Example fix
// before const p = await getPresenter(client, myCustomClass, key) // after setObjectPresenter(myCustomClass, myPlugin.component.MyCardPresenter) // register first const p = await getPresenter(client, myCustomClass, key)
Defensive patterns
Strategy: fallback
Validate before calling
const p = await getObjectPresenter(client, _class) ?? defaultObjectPresenter
Type guard
function hasObjectPresenter(cls: Ref<Class<Doc>>): boolean { return getObjectPresenterSync(cls) !== undefined } Try / catch
try { return await getPresenter(client, _class, key) } catch { return genericObjectPresenter } Prevention
- Register default object presenters for all custom classes
- Verify lookup target classes have presenters
- Include presenter plugins in every deployment
- Snapshot-test presenters for key classes
When it happens
Trigger: Rendering a reference/lookup column (or any key where key.key.length === 0) for a class that has no object presenter registered via getObjectPresenter registry.
Common situations: Custom/derived classes without a default presenter; lookup keys ($lookup...) used where the target class lacks a presenter; plugin with the object presenter not loaded; class renamed/refactored leaving the registry stale.
Related errors
- attribute presenter not found for ${JSON.stringify(preserveK
- Space type #${space.type} not found
- lookup class does not provided for ${key.key}
- presenter not found for ${_class}
- No screen access granted
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/4ea5d491de8ae08f.
Report an issue: GitHub.