hcengineering/platform · error · Error
descendants not found: ${_class}
Error message
descendants not found: ${_class} What it means
Hierarchy.getDescendants returns the precomputed list of descendant classes for a registered classifier from the internal descendants map. The map is populated during hierarchy construction (updateDescendant). If the class was never added to the hierarchy, no descendant entry exists and this Error is thrown.
Source
Thrown at foundations/core/packages/core/src/hierarchy.ts:390
*/
private isExtends<T extends Doc>(extendsOrImplements: Ref<Interface<Doc>>[], from: Ref<Interface<T>>): boolean {
const result: Ref<Interface<Doc>>[] = []
const toVisit = [...extendsOrImplements]
while (toVisit.length > 0) {
const ref = toVisit.shift() as Ref<Interface<Doc>>
if (ref === from) {
return true
}
addIf(result, ref)
toVisit.push(...this.ancestorsOf(ref))
}
return false
}
getDescendants<T extends Obj>(_class: Ref<Class<T>>): Ref<Class<Obj>>[] {
const data = this.descendants.get(_class)
if (data === undefined) {
throw new Error('descendants not found: ' + _class)
}
return data
}
private updateDescendant (_class: Ref<Classifier>, add = true): void {
let hierarchy: Ref<Classifier>[] = []
try {
hierarchy = this.getAncestors(_class)
} catch (err) {
if (add) {
throw err
}
}
for (const cls of hierarchy) {
const list = this.descendants.get(cls)
if (list === undefined) {View on GitHub (pinned to 63e28dc964)
Solutions
- Ensure all model txes (including the class definition) have been applied via hierarchy.addedTx before querying descendants
- Verify the class ref belongs to an installed model package
- For optional classes, filter with hierarchy.findClass first or wrap in try/catch
- Check initialization order so descendants queries happen after hierarchy hydration
Example fix
// before
const sub = hierarchy.getDescendants(core.class.Doc)
// after
if (hierarchy.findClass(core.class.Doc) === undefined) {
throw new Error('Hierarchy not initialized - model txes missing')
}
const sub = hierarchy.getDescendants(core.class.Doc) Defensive patterns
Strategy: validation
Validate before calling
if (hierarchy.findClass(_class) === undefined) {
throw new Error(`Hierarchy not initialized for ${String(_class)} - missing model tx`)
}
const descendants = hierarchy.getDescendants(_class) Type guard
function hasDescendants(h: Hierarchy, c: Ref<Class<Obj>>): boolean {
return h.findClass(c) !== undefined
} Try / catch
let subtypes: Ref<Class<Obj>>[]
try {
subtypes = hierarchy.getDescendants(_class)
} catch (err) {
console.error(`Descendants unavailable for ${String(_class)}; hierarchy not hydrated`, err)
throw err
} Prevention
- Initialize hierarchy from the complete model tx batch before querying
- Sequence startup so descendant-dependent features run after model hydration
- Use findClass as a cheap existence probe first
- Load all plugin models, not just the ones in direct use
When it happens
Trigger: Calling getDescendants (directly or via classes, descendants, isClassIndexable, getFullTextIndexableAttributes) with a class ref whose hierarchy.addedTx was never processed; calling before initial model sync completes.
Common situations: Querying descendants during startup before the model transaction batch finishes; plugin model not installed; constructing a fresh Hierarchy in tests without replaying all classifier txes.
Related errors
- interface not found: ${_interface}
- domain not found: ${_class}
- ancestors not found: ${_class}
- class not found: ${_class}
- attribute not found: ${name}
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/1375e3ef175fb1c9.
Report an issue: GitHub.