hcengineering/platform · error
Descriptor is not found in the model
Error message
Descriptor is not found in the model
What it means
createSpaceType creates a SpaceType object whose Data carries a descriptor reference. Before creating the object, the code looks the descriptor up in the client's model via findObject(data.descriptor); if no such model object exists it throws this error. It is a guard against creating space types whose descriptor was never registered in the model (e.g. by a plugin that isn't loaded).
Source
Thrown at plugins/setting/src/utils.ts:41
Space,
SpaceType,
TxOperations,
TypeAny as TypeAnyType,
getRoleAttributeLabel
} from '@hcengineering/core'
import { getEmbeddedLabel, IntlString } from '@hcengineering/platform'
import setting from './index'
export async function createSpaceType<T extends SpaceType> (
client: TxOperations,
data: Omit<Data<T>, 'targetClass'>,
_id: Ref<T>,
_class: Ref<Class<T>> = core.class.SpaceType
): Promise<Ref<T>> {
const descriptorObj = client.getModel().findObject(data.descriptor)
if (descriptorObj === undefined) {
throw new Error('Descriptor is not found in the model')
}
const baseClassClazz = client.getHierarchy().getClass(descriptorObj.baseClass)
// NOTE: it is important for this id to be consistent when re-creating the same
// space type with the same id as it will happen during every migration if type is created by the system
const spaceTypeMixinId = `${_id}:type:mixin` as Ref<Class<Space>>
await client.createDoc(
core.class.Mixin,
core.space.Model,
{
extends: descriptorObj.baseClass,
kind: ClassifierKind.MIXIN,
label: getEmbeddedLabel(data.name),
icon: baseClassClazz.icon
},
spaceTypeMixinId
)
View on GitHub (pinned to 63e28dc964)
Solutions
- Verify the descriptor plugin defining the Ref<SpaceTypeDescriptor> is included in the client's plugin configuration and loaded before createSpaceType is called
- Print client.getModel().findObject(data.descriptor) and compare the id with the constant exported by the descriptor plugin to catch typos
- If the descriptor was renamed/moved, update the caller to the new exported id instead of a string literal
- Ensure the model is built with all required plugins (check the plugin list passed to the model builder in this app/test)
Example fix
// before
await createSpaceType(client, { descriptor: 'myapp:desc:Custom' as Ref<SpaceTypeDescriptor>, name: 'Custom', icon: ... })
// after
const descriptor = myPlugin.descriptors.Custom // exported, type-checked id
if (client.getModel().findObject(descriptor) === undefined) {
throw new Error('Plugin providing descriptor ' + descriptor + ' is not loaded')
}
await createSpaceType(client, { descriptor, name: 'Custom', icon: ... }) Defensive patterns
Strategy: validation
Validate before calling
function canCreateSpaceType<T extends SpaceType>(client: TxOperations, data: Data<T>): boolean {
return client.getModel().findObject(data.descriptor) !== undefined
}
// call before: if (!canCreateSpaceType(client, data)) throw new Error('Descriptor plugin not loaded') Type guard
function isDescriptorInModel<T extends SpaceType>(client: TxOperations, ref: Ref<SpaceTypeDescriptor>): ref is Ref<SpaceTypeDescriptor> {
return client.getModel().findObject(ref) !== undefined
} Try / catch
try {
await createSpaceType(client, data, _id)
} catch (err) {
if (err instanceof Error && err.message === 'Descriptor is not found in the model') {
console.error('Descriptor missing from model:', data.descriptor, '- check plugin list')
}
throw err
} Prevention
- Always reference descriptors via plugin-exported constants, never string literals
- Keep the client's plugin list in sync with every space type you create
- Add an early model assertion in tests for each descriptor used in fixtures
When it happens
Trigger: Calling createSpaceType with data.descriptor set to a Ref<SpaceTypeDescriptor> that is absent from the model — typically because the plugin defining that descriptor is not installed/enabled, the descriptor id is misspelled, or client.getModel() is built from an incomplete plugin list.
Common situations: Adding a custom space type after removing/renaming its descriptor plugin; using a descriptor from another product/plugin version; tests or migrations running with a trimmed plugin set that excludes the descriptor's plugin.
Related errors
- category is not found in model
- ancestors not found: ${_class}
- class not found: ${_class}
- Map is not allowed in model
- Set is not allowed in model
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/3c81dac5c3d09f92.
Report an issue: GitHub.