hcengineering/platform · error · Error

Model txes must target only core.space.Model

Error message

Model txes must target only core.space.Model

What it means

initModel (server/tool/src/index.ts:125) validates that every transaction in the provided tx array targets the model space (core.space.Model) before building the workspace model. If any tx has a different objectSpace, model construction would mix domain data into the model, so it throws immediately before creating the database.

Source

Thrown at server/tool/src/index.ts:125

    txes: JSON.parse(JSON.stringify(rawTxes)) as Tx[]
  }
}

/**
 * @public
 */
export async function initModel (
  ctx: MeasureContext,
  workspaceId: WorkspaceUuid,
  rawTxes: Tx[],
  adapter: DbAdapter,
  storageAdapter: StorageAdapter,
  logger: ModelLogger = consoleModelLogger,
  progress: (value: number) => Promise<void>
): Promise<void> {
  const { txes } = prepareTools(rawTxes)
  if (txes.some((tx) => tx.objectSpace !== core.space.Model)) {
    throw Error('Model txes must target only core.space.Model')
  }

  try {
    logger.log('creating database...', { workspaceId })
    const firstTx: Tx = {
      _class: core.class.Tx,
      _id: 'first-tx' as Ref<Tx>,
      modifiedBy: core.account.System,
      modifiedOn: Date.now(),
      space: core.space.DerivedTx,
      objectSpace: core.space.DerivedTx
    }

    await adapter.upload(ctx, DOMAIN_TX, [firstTx])

    await progress(30)

    logger.log('creating data...', { workspaceId })

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Filter txes to model space before calling: `txes.filter(tx => tx.objectSpace === core.space.Model)`.
  2. Ensure every model tx is created via model helpers (Tx.createTxCreate etc.) with `objectSpace: core.space.Model`.
  3. Check the plugin list passed to prepareTools — a custom plugin may emit txes targeting a domain space; fix that plugin.
  4. Log offending txes (`txes.filter(t => t.objectSpace !== core.space.Model)`) to identify the source.

Example fix

// before
await initModel(ctx, workspaceId, allTxes, ...)
// after
const modelTxes = allTxes.filter((tx) => tx.objectSpace === core.space.Model)
await initModel(ctx, workspaceId, modelTxes, ...)
Defensive patterns

Strategy: validation

Validate before calling

import { core } from '@hcengineering/core'
const bad = txes.filter((tx) => tx.objectSpace !== core.space.Model)
if (bad.length > 0) throw new Error(`${bad.length} tx(es) do not target core.space.Model`)

Type guard

function isModelTx(tx: Tx): boolean {
  return tx.objectSpace === core.space.Model
}

Try / catch

try {
  await createWorkspace(ctx, workspaceId, txes)
} catch (err) {
  if ((err as Error).message === 'Model txes must target only core.space.Model') {
    console.error('Non-model tx present; filter txes to core.space.Model')
  }
  throw err
}

Prevention

When it happens

Trigger: Calling createWorkspace (which calls initModel) with raw txes that include transactions whose objectSpace !== core.space.Model — e.g. passing both model and domain/document txes, or hand-built txes missing objectSpace: core.space.Model.

Common situations: Custom workspace-creation scripts passing mixed tx sets; plugins whose derived txes lost objectSpace after a refactor; migrating model data from another system where the space field was dropped.

Related errors


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