hcengineering/platform · error
Add collection step must have attachedTo, attachedToClass, c
Error message
Add collection step must have attachedTo, attachedToClass, collection and space
What it means
The initializer's create() method has a special branch for 'add collection' migration steps, which require attachedTo, attachedToClass, collection and space in the step data. If any of these four fields is undefined, the step is malformed and the migration cannot attach a collection, so it throws immediately before calling client.addCollection. This is a fail-fast validation of the migration/fixture data shape.
Source
Thrown at server/tool/src/initializer.ts:300
}
private parseMarkdown (text: string): string {
const json = markdownToMarkup(text ?? '', { imageUrl: this.imageUrl })
return JSON.stringify(json)
}
private async create<T extends Doc>(_class: Ref<Class<T>>, data: Props<T>, _id?: Ref<T>): Promise<Ref<T>> {
const hierarchy = this.client.getHierarchy()
if (hierarchy.isDerived(_class, core.class.AttachedDoc)) {
const { space, attachedTo, attachedToClass, collection, ...props } = data as unknown as Props<AttachedDoc>
if (
attachedTo === undefined ||
space === undefined ||
attachedToClass === undefined ||
collection === undefined
) {
throw new Error('Add collection step must have attachedTo, attachedToClass, collection and space')
}
return (await this.client.addCollection(
_class,
space,
attachedTo,
attachedToClass,
collection,
props,
_id as Ref<AttachedDoc> | undefined
)) as unknown as Ref<T>
} else {
const { space, ...props } = data
if (space === undefined) {
throw new Error('Create step must have space')
}
return await this.client.createDoc<T>(_class, space, props as Data<T>, _id)
}
}View on GitHub (pinned to 63e28dc964)
Solutions
- Add all four required fields (attachedTo, attachedToClass, collection, space) to the step data
- Log the data object before calling create() to see which field is undefined
- Check the upstream code that constructs the step for a key typo or failed lookup returning undefined
Example fix
// before
await initializer.create(_class, { collection: 'comments' } as any)
// after
await initializer.create(_class, {
attachedTo: parentId,
attachedToClass: 'task:task:Task',
collection: 'comments',
space: mySpace
}) Defensive patterns
Strategy: validation
Validate before calling
function isValidAddCollectionStep(data) {
return data != null &&
data.attachedTo !== undefined &&
data.attachedToClass !== undefined &&
data.collection !== undefined &&
data.space !== undefined
}
if (!isValidAddCollectionStep(step)) throw new Error('Invalid add collection step: ' + JSON.stringify(step)) Type guard
function isAddCollectionStep(d: unknown): d is { attachedTo: Ref<Doc>, attachedToClass: string, collection: string, space: Ref<Space> } & Record<string, any> {
const o = d as any
return o != null && typeof o.collection === 'string' && o.attachedTo !== undefined && o.attachedToClass !== undefined && o.space !== undefined
} Try / catch
try {
await initializer.create(_class, data)
} catch (err) {
if (err instanceof Error && err.message.includes('Add collection step must have')) {
console.error('Malformed add-collection step, missing fields:', data)
}
throw err
} Prevention
- Type step data with a discriminated union so attached steps require attachedTo/attachedToClass/collection/space
- Validate all migration steps before executing them (dry-run validation pass)
- Avoid spreading objects that can silently introduce undefined values for required keys
When it happens
Trigger: Calling create() (via processCreate) with a _class that resolves to the add-collection branch while the data object omits or misspells one of attachedTo, attachedToClass, collection or space (e.g. fields set to undefined by a spread or upstream transform).
Common situations: Migration step objects built dynamically where a variable was undefined; typos in step keys (e.g. attachedTo missing because the parent doc id wasn't resolved); copy-pasted step definitions from a different step type that doesn't carry collection fields.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Create step must have space
- Failed to load server config
- getDisplayMedia not supported
- No screen access granted
- Message id is required
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/0b2e797cdd15a4d2.
Report an issue: GitHub.