hcengineering/platform · error

Cannot create card with base type ${type}

Error message

Cannot create card with base type ${type}

What it means

createCard rejects types for which isBaseTypeWithSubtypes(hierarchy, type) is true — abstract/base card types that only exist to be subclassed and have no direct instances. Instantiating such a type would produce an invalid card, so the function throws.

Source

Thrown at plugins/card-resources/src/utils.ts:586

      docCreatedBy: card.docCreatedBy ?? card.createdBy ?? card.modifiedBy
    },
    mixin,
    true
  )
}

export async function createCard (
  type: Ref<MasterTag>,
  space: Ref<Space>,
  data: Partial<Data<Card>> = {},
  contentMarkup: Markup = EmptyMarkup,
  id?: Ref<Card>
): Promise<Ref<Card>> {
  const client = getClient()
  const hierarchy = client.getHierarchy()

  if (isBaseTypeWithSubtypes(hierarchy, type)) {
    throw new Error(`Cannot create card with base type ${type}`)
  }

  const title = data.title ?? (await translate(card.string.Card, {}))

  const _id = id ?? generateId()
  const content = isEmptyMarkup(contentMarkup)
    ? ('' as MarkupBlobRef)
    : await createMarkup(makeCollabId(type, _id, 'content'), contentMarkup)

  const _data: Data<Card> = {
    parentInfo: [],
    blobs: {},
    ...data,
    title,
    rank: '',
    content
  }

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Pass a concrete card subtype class (one without registered subtypes) instead of the base type
  2. Check with isBaseTypeWithSubtypes in UI code and hide base types from creation pickers
  3. Update cardFactory configurations/default types to concrete classes

Example fix

// before
await createCard(type, space, data) // type is base card class
// after
if (isBaseTypeWithSubtypes(hierarchy, type)) {
  type = concreteSubtypeFor(type) // pick a registered subtype
}
await createCard(type, space, data)
Defensive patterns

Strategy: validation

Validate before calling

const hierarchy = client.getHierarchy()
if (isBaseTypeWithSubtypes(hierarchy, type)) {
  type = pickConcreteSubtype(type) // must resolve to a non-base class
}

Type guard

const isConcreteCardType = (h: Hierarchy, type: Ref<Class<Card>>): boolean =>
  !isBaseTypeWithSubtypes(h, type)

Try / catch

try {
  await createCard(type, space, data)
} catch (err) {
  if ((err as Error).message.startsWith('Cannot create card with base type')) {
    // prompt user to pick a concrete card kind
  } else throw err
}

Prevention

When it happens

Trigger: Calling createCard (directly or via cardFactory) with a base/abstract card class — e.g. passing card.class.Card or another parent type instead of a concrete subtype like a task or issue class.

Common situations: Generic UI letting users pick 'Card' instead of a concrete kind; factory code defaulting to the base type when no subtype specified; plugins registering new subtypes but old configs still referencing the base class.

Related errors


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