hcengineering/platform · error · Error

createDoc cannot be used for objects inherited from Attached

Error message

createDoc cannot be used for objects inherited from AttachedDoc

What it means

OperationalOperations.createDoc creates top-level documents via a TxCreateDoc. AttachedDoc instances (attachments, comments, etc.) must be created with createAttachedDoc so their attachedTo/attachedToClass are wired and collection counters updated; calling createDoc for such classes is rejected with this plain Error.

Source

Thrown at foundations/core/packages/core/src/operations.ts:111

  searchFulltext (query: SearchQuery, options: SearchOptions): Promise<SearchResult> {
    return this.client.searchFulltext(query, options)
  }

  tx (tx: Tx): Promise<TxResult> {
    return this.client.tx(tx)
  }

  async createDoc<T extends Doc>(
    _class: Ref<Class<T>>,
    space: Ref<Space>,
    attributes: Data<T>,
    id?: Ref<T>,
    modifiedOn?: Timestamp,
    modifiedBy?: PersonId
  ): Promise<Ref<T>> {
    const hierarchy = this.client.getHierarchy()
    if (hierarchy.isDerived(_class, core.class.AttachedDoc)) {
      throw new Error('createDoc cannot be used for objects inherited from AttachedDoc')
    }
    if (hierarchy.findDomain(_class) === DOMAIN_MODEL && space !== core.space.Model) {
      throw new Error('createDoc cannot be called for DOMAIN_MODEL classes with non-model space')
    }
    const tx = this.txFactory.createTxCreateDoc(_class, space, attributes, id, modifiedOn, modifiedBy)
    await this.tx(tx)
    return tx.objectId
  }

  async addCollection<T extends Doc, P extends AttachedDoc>(
    _class: Ref<Class<P>>,
    space: Ref<Space>,
    attachedTo: Ref<T>,
    attachedToClass: Ref<Class<T>>,
    collection: Extract<keyof T, string> | string,
    attributes: AttachedData<P>,
    id?: Ref<P>,
    modifiedOn?: Timestamp,

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Use createAttachedDoc(...) for classes derived from AttachedDoc, providing attachedTo/attachedToClass/collection
  2. Branch on hierarchy.isDerived(_class, core.class.AttachedDoc) to choose the right creation API
  3. If the class should be top-level, change it so it no longer extends AttachedDoc
  4. Update generic helpers to detect AttachedDoc subclasses and route accordingly

Example fix

// before
await ops.createDoc(comment.class.Comment, space, { message })
// after
await ops.createAttachedDoc(
  comment.class.Comment,
  space,
  { message },
  parentDoc._id,
  parentDoc._class,
  'comments'
)
Defensive patterns

Strategy: type-guard

Validate before calling

const hierarchy = client.getHierarchy()
if (hierarchy.isDerived(_class, core.class.AttachedDoc)) {
  throw new Error(`${String(_class)} is an AttachedDoc; use createAttachedDoc`)
}
await ops.createDoc(_class, space, attributes)

Type guard

function isAttachedClass(h: Hierarchy, c: Ref<Class<Doc>>): boolean {
  return h.isDerived(c, core.class.AttachedDoc)
}

Try / catch

try {
  await ops.createDoc(_class, space, attrs)
} catch (err) {
  if ((err as Error).message.includes('AttachedDoc')) {
    return ops.createAttachedDoc(_class as Ref<AttachedDoc>, space, attrs, attachedTo, attachedToClass, collection)
  }
  throw err
}

Prevention

When it happens

Trigger: Calling createDoc with a _class parameter that derives from core.class.AttachedDoc (checked via hierarchy.isDerived), e.g. trying to create a Comment, Attachment, or custom attached object as if it were a space-level document.

Common situations: Copying creation code between a parent doc and its attachment; refactoring a Doc subclass into an AttachedDoc subclass without updating creation sites; generic factory functions that pass arbitrary class refs.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/1b5a75ad517c6945. Report an issue: GitHub.