{"record":{"id":"029d0e8c3c23b991","repo":"hcengineering/platform","slug":"mixin-step-must-have-id-and-space","errorCode":null,"errorMessage":"Mixin step must have _id and space","messagePattern":"Mixin step must have _id and space","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/tool/src/initializer.ts","lineNumber":231,"sourceCode":"    }\n  }\n\n  private async processFind<T extends Doc>(step: FindStep<T>, vars: Record<string, any>): Promise<void> {\n    const query = this.fillProps(step.query, vars)\n    const res = await this.client.findOne(step._class, { ...(query as any) })\n    if (res === undefined) {\n      throw new Error(`Document not found: ${JSON.stringify(query)}`)\n    }\n    if (step.resultVariable !== undefined) {\n      vars[`\\${${step.resultVariable}}`] = res\n    }\n  }\n\n  private async processMixin<T extends Doc>(step: MixinStep<T, T>, vars: Record<string, any>): Promise<void> {\n    const data = await this.fillPropsWithMarkdown(step.data, vars, step.markdownFields)\n    const { _id, space, ...props } = data\n    if (_id === undefined || space === undefined) {\n      throw new Error('Mixin step must have _id and space')\n    }\n    await this.client.createMixin(_id, step._class, space, step.mixin, props)\n  }\n\n  private async processUpdate<T extends Doc>(step: UpdateStep<T>, vars: Record<string, any>): Promise<void> {\n    const data = await this.fillPropsWithMarkdown(step.data, vars, step.markdownFields)\n    const { _id, space, ...props } = data\n    if (_id === undefined || space === undefined) {\n      throw new Error('Update step must have _id and space')\n    }\n    await this.client.updateDoc(step._class, space, _id as Ref<Doc>, props)\n  }\n\n  private async processBulkUpdate<T extends Doc>(step: BulkUpdateStep<T>, vars: Record<string, any>): Promise<void> {\n    const ops = this.client.apply()\n    const docs = await this.client.findAll(step._class, { ...(step.query as any) })\n    const data = await this.fillPropsWithMarkdown(step.data, vars, step.markdownFields)\n    for (const doc of docs) {","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/tool/src/initializer.ts#L213-L249","documentation":"A MixinStep's filled data must identify the target document by its _id and space, since createMixin needs both to locate and update the document. If either is missing after variable substitution, the step is malformed and the initializer throws this error. This is a script-authoring error, not a runtime infrastructure failure.","triggerScenarios":"A MixinStep whose data object (after fillPropsWithMarkdown substitution) lacks _id or space — e.g. the step data references variables that resolved to undefined, or the author simply omitted them.","commonSituations":"Hand-written init/update scripts forgetting _id/space in mixin steps; a ${var} placeholder not bound by an earlier Find step, resolving to undefined; refactoring of script JSON that dropped required fields.","solutions":["Add the target document's _id and space to the step data.","Bind the missing value via an earlier FindStep setting a resultVariable, and reference it (${...}) in the mixin data.","Log/print the filled data before the call to see which field resolved to undefined."],"exampleFix":"// before\n{ \"_class\": \"contact:class:Person\", \"mixin\": \"...\", \"data\": { \"rank\": 5 } }\n// after\n{ \"_class\": \"contact:class:Person\", \"mixin\": \"...\", \"data\": { \"_id\": \"contact:person:Id\", \"space\": \"core:space:Space\", \"rank\": 5 } }","handlingStrategy":"validation","validationCode":"for (const step of script.steps) {\n  if (stepIsMixin(step) && (step.data._id === undefined || step.data.space === undefined)) {\n    throw new Error(`MixinStep missing _id/space: ${JSON.stringify(step).slice(0, 120)}`)\n  }\n}","typeGuard":"function hasIdAndSpace<T extends Doc>(d: Partial<T> | undefined): d is T & { _id: Ref<T>, space: Ref<Space> } {\n  return d !== undefined && d._id !== undefined && (d as any).space !== undefined\n}","tryCatchPattern":"try {\n  await this.client.createMixin(_id, step._class, space, step.mixin, props)\n} catch (err) {\n  if ((err as Error).message === 'Mixin step must have _id and space') {\n    console.error('MixinStep data must include _id and space; check variable bindings', step)\n  }\n  throw err\n}","preventionTips":["Always include _id and space in mixin step data.","Bind referenced variables with a prior FindStep resultVariable.","Validate scripts (assert identity fields) before running against a workspace.","Log filled data for failing steps to spot undefined substitutions."],"tags":["initialization","mixin","validation","missing-field"],"backgroundTag":"missing-required-fields","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}