{"record":{"id":"1a94f87f82e5f2a4","repo":"angular/angular-cli","slug":"a-schematic-was-called-from-a-different-engine-as","errorCode":null,"errorMessage":"A schematic was called from a different engine as its parent.","messagePattern":"A schematic was called from a different engine as its parent\\.","errorType":"exception","errorClass":"SchematicEngineConflictingException","httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/schematics/src/engine/engine.ts","lineNumber":248,"sourceCode":"          description,\n          new Set(parentNames),\n        );\n\n        bases.unshift(base, ...baseBases);\n      }\n    }\n\n    return [description, bases];\n  }\n\n  createContext(\n    schematic: Schematic<CollectionT, SchematicT>,\n    parent?: Partial<TypedSchematicContext<CollectionT, SchematicT>>,\n    executionOptions?: Partial<ExecutionOptions>,\n  ): TypedSchematicContext<CollectionT, SchematicT> {\n    // Check for inconsistencies.\n    if (parent && parent.engine && parent.engine !== this) {\n      throw new SchematicEngineConflictingException();\n    }\n\n    let interactive = true;\n    if (executionOptions && executionOptions.interactive != undefined) {\n      interactive = executionOptions.interactive;\n    } else if (parent && parent.interactive != undefined) {\n      interactive = parent.interactive;\n    }\n\n    let context: TypedSchematicContext<CollectionT, SchematicT> = {\n      debug: (parent && parent.debug) || false,\n      engine: this,\n      logger:\n        (parent && parent.logger && parent.logger.createChild(schematic.description.name)) ||\n        new logging.NullLogger(),\n      schematic,\n      strategy:\n        parent && parent.strategy !== undefined ? parent.strategy : this.defaultMergeStrategy,","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/schematics/src/engine/engine.ts#L230-L266","documentation":"Each SchematicEngine instance owns its own collection/schematic registries and task schedulers. When creating an execution context for a schematic, if the supplied parent context carries an \"engine\" reference that is a different engine instance than the one being asked to create the context, the parent-child relationship is invalid, so SchematicEngineConflictingException is thrown. The engine refuses to mix contexts across engine instances because task scheduling and merge strategies would otherwise be attributed to the wrong engine.","triggerScenarios":"Calling engine.createContext(schematic, parentContext) where parentContext.engine is set and !== the engine instance the method is invoked on — typically when schematic code captures a context from one engine (e.g. created by an external SchematicEngine) and passes it as parent to another engine's createContext, or when invoking a schematic through a second engine instance while passing the first engine's context along.","commonSituations":"Custom CLI or builder code that instantiates more than one SchematicEngine and shares contexts between them; library code that stores a global parent context and reuses it after a new engine was created (common in tests that build a fresh engine per test); running a schematic inside another schematic but through a separately constructed engine instead of engine.registry/context from the current context.","solutions":["Invoke createContext on the same engine instance that owns the parent context (use parent.engine.createContext(...) instead of a different engine).","Ensure a single SchematicEngine instance is created per execution and pass that one to all schematic/code invocations.","If crossing engines is intentional, omit the \"engine\" field on the parent (pass a parent without engine) or don't pass a parent at all.","In nested schematic calls, use the current context's engine (context.engine) rather than constructing a new engine."],"exampleFix":"// before\nconst otherEngine = new SchematicEngine(host);\nconst ctx = otherEngine.createContext(schematic, parentContext); // parentContext.engine !== otherEngine\n\n// after\nconst ctx = parentContext.engine.createContext(schematic, parentContext);","handlingStrategy":"validation","validationCode":"function canUseAsParent(engine: SchematicEngine, parent?: Partial<TypedSchematicContext<any, any>>): boolean {\n  return !parent || !parent.engine || parent.engine === engine;\n}\nif (canUseAsParent(engine, parentContext)) {\n  engine.createContext(schematic, parentContext);\n}","typeGuard":"function belongsToEngine<T, C extends { engine?: unknown }>(engine: SchematicEngine<T, any>, ctx: C): ctx is C & { engine: SchematicEngine<T, any> } {\n  return ctx.engine === undefined || ctx.engine === engine;\n}","tryCatchPattern":"import { SchematicEngineConflictingException } from '@angular-devkit/schematics';\ntry {\n  const ctx = engine.createContext(schematic, parentContext);\n} catch (e) {\n  if (e instanceof SchematicEngineConflictingException) {\n    const ctx = parentContext.engine.createContext(schematic, parentContext);\n  } else { throw e; }\n}","preventionTips":["Create exactly one SchematicEngine per execution and thread it through your code instead of instantiating new engines ad hoc.","When delegating to another engine, pass a parent without its engine field (or no parent) instead of the foreign context.","In tests, build engine + host per fixture and never share captured contexts between engines."],"tags":["schematics","engine","context","misuse"],"backgroundTag":"wrong-engine-context","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}