{"record":{"id":"0b2e797cdd15a4d2","repo":"hcengineering/platform","slug":"add-collection-step-must-have-attachedto-attached-0b2e79","errorCode":null,"errorMessage":"Add collection step must have attachedTo, attachedToClass, collection and space","messagePattern":"Add collection step must have attachedTo, attachedToClass, collection and space","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/tool/src/initializer.ts","lineNumber":300,"sourceCode":"  }\n\n  private parseMarkdown (text: string): string {\n    const json = markdownToMarkup(text ?? '', { imageUrl: this.imageUrl })\n    return JSON.stringify(json)\n  }\n\n  private async create<T extends Doc>(_class: Ref<Class<T>>, data: Props<T>, _id?: Ref<T>): Promise<Ref<T>> {\n    const hierarchy = this.client.getHierarchy()\n\n    if (hierarchy.isDerived(_class, core.class.AttachedDoc)) {\n      const { space, attachedTo, attachedToClass, collection, ...props } = data as unknown as Props<AttachedDoc>\n      if (\n        attachedTo === undefined ||\n        space === undefined ||\n        attachedToClass === undefined ||\n        collection === undefined\n      ) {\n        throw new Error('Add collection step must have attachedTo, attachedToClass, collection and space')\n      }\n      return (await this.client.addCollection(\n        _class,\n        space,\n        attachedTo,\n        attachedToClass,\n        collection,\n        props,\n        _id as Ref<AttachedDoc> | undefined\n      )) as unknown as Ref<T>\n    } else {\n      const { space, ...props } = data\n      if (space === undefined) {\n        throw new Error('Create step must have space')\n      }\n      return await this.client.createDoc<T>(_class, space, props as Data<T>, _id)\n    }\n  }","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/tool/src/initializer.ts#L282-L318","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nawait initializer.create(_class, { collection: 'comments' } as any)\n// after\nawait initializer.create(_class, {\n  attachedTo: parentId,\n  attachedToClass: 'task:task:Task',\n  collection: 'comments',\n  space: mySpace\n})","handlingStrategy":"validation","validationCode":"function isValidAddCollectionStep(data) {\n  return data != null &&\n    data.attachedTo !== undefined &&\n    data.attachedToClass !== undefined &&\n    data.collection !== undefined &&\n    data.space !== undefined\n}\nif (!isValidAddCollectionStep(step)) throw new Error('Invalid add collection step: ' + JSON.stringify(step))","typeGuard":"function isAddCollectionStep(d: unknown): d is { attachedTo: Ref<Doc>, attachedToClass: string, collection: string, space: Ref<Space> } & Record<string, any> {\n  const o = d as any\n  return o != null && typeof o.collection === 'string' && o.attachedTo !== undefined && o.attachedToClass !== undefined && o.space !== undefined\n}","tryCatchPattern":"try {\n  await initializer.create(_class, data)\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Add collection step must have')) {\n    console.error('Malformed add-collection step, missing fields:', data)\n  }\n  throw err\n}","preventionTips":["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"],"tags":["validation","migration","initializer"],"backgroundTag":"missing-required-field","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}