hcengineering/platform · error
category is not found in model
Error message
category is not found in model
What it means
createProjectType builds a ProjectType from a descriptor reference; it looks up data.descriptor in the model with findObject and throws this error when the descriptor (a ProjectTypeDescriptor / category object) is absent. Like the space-type counterpart, it guards against creating project types whose descriptor plugin is not part of the loaded model.
Source
Thrown at plugins/task/src/utils.ts:204
*/
export async function createProjectType (
client: TxOperations,
data: ProjectData,
tasks: TaskTypeWithFactory[],
_id: Ref<ProjectType>
): Promise<Ref<ProjectType>> {
const current = await client.findOne(task.class.ProjectType, { _id })
if (current !== undefined) {
return current._id
}
const _tasks: Ref<TaskType>[] = []
const tasksData = new Map<Ref<TaskType>, Data<TaskType>>()
const _statues = new Set<Ref<Status>>()
const categoryObj = client.getModel().findObject(data.descriptor)
if (categoryObj === undefined) {
throw new Error('category is not found in model')
}
await createTaskTypes(tasks, _id, client, _statues, tasksData, _tasks, false)
const baseClassClass = client.getHierarchy().getClass(categoryObj.baseClass)
// NOTE: it is important for this id to be consistent when re-creating the same
// project type with the same id as it will happen during every migration if type is created by the system
const targetProjectClassId = `${_id}:type:mixin` as Ref<Class<Doc>>
const tmpl = await client.createDoc(
task.class.ProjectType,
core.space.Model,
{
description: data.description,
shortDescription: data.shortDescription,
descriptor: data.descriptor,
roles: 0,
tasks: _tasks,View on GitHub (pinned to 63e28dc964)
Solutions
- Confirm the plugin exporting the descriptor is loaded into the client model before calling createProjectType
- Use the exported descriptor constant from the plugin instead of a hand-written string id
- Dump client.getModel().findObject(data.descriptor) / list model objects of the descriptor class to verify presence and exact id
- If descriptors changed across versions, migrate references to the new descriptor ids
Example fix
// before
await createProjectTypeWithTaskTypes(client, { descriptor: 'task:desc:Kanban' as Ref<ProjectTypeDescriptor>, ... })
// after
const descriptor = taskPlugin.descriptors.Kanban
if (client.getModel().findObject(descriptor) === undefined) {
throw new Error('Descriptor plugin not loaded: ' + descriptor)
}
await createProjectTypeWithTaskTypes(client, { descriptor, ... }) Defensive patterns
Strategy: validation
Validate before calling
function canCreateProjectType (client: TxOperations, data: Data<ProjectType>): boolean {
return client.getModel().findObject(data.descriptor) !== undefined
}
// before createProjectType: if (!canCreateProjectType(client, data)) throw new Error('Descriptor plugin not loaded: ' + data.descriptor) Type guard
function isDescriptorInModel (client: TxOperations, ref: Ref<ProjectTypeDescriptor>): boolean {
return client.getModel().findObject(ref) !== undefined
} Try / catch
try {
await createProjectTypeWithTaskTypes(client, data, tasks)
} catch (err) {
if (err instanceof Error && err.message.includes('category is not found in model')) {
console.error('Project type descriptor missing:', data.descriptor, '- check plugin configuration')
}
throw err
} Prevention
- Import descriptor ids from plugin exports rather than raw strings
- Run a model completeness check in tests for all project types created in fixtures
- Re-audit descriptor references after plugin renames/upgrades
When it happens
Trigger: Calling createProjectType (often via createProjectTypeWithTaskTypes) with a descriptor Ref not present in client.getModel() — missing plugin, wrong/renamed descriptor id, or model built from an incomplete plugin set.
Common situations: Custom project types referencing descriptors from a plugin removed in an upgrade; copy-pasted string ids instead of plugin exports; migrations running before all descriptor plugins are registered.
Related errors
- Descriptor is not found in the 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/ed0e8427718a6c72.
Report an issue: GitHub.