{"record":{"id":"0e0ac70a75bd39f5","repo":"angular/angular-cli","slug":"expected-a-synchronous-delegate-but-got-an-asynchr","errorCode":null,"errorMessage":"Expected a synchronous delegate but got an asynchronous one.","messagePattern":"Expected a synchronous delegate but got an asynchronous one\\.","errorType":"exception","errorClass":"SynchronousDelegateExpectedException","httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/core/src/virtual-fs/host/sync.ts","lineNumber":34,"sourceCode":"  HostCapabilities,\n  HostWatchEvent,\n  HostWatchOptions,\n  Stats,\n} from './interface';\n\nexport class SynchronousDelegateExpectedException extends BaseException {\n  constructor() {\n    super(`Expected a synchronous delegate but got an asynchronous one.`);\n  }\n}\n\n/**\n * Implement a synchronous-only host interface (remove the Observable parts).\n */\nexport class SyncDelegateHost<T extends object = {}> {\n  constructor(protected _delegate: Host<T>) {\n    if (!_delegate.capabilities.synchronous) {\n      throw new SynchronousDelegateExpectedException();\n    }\n  }\n\n  protected _doSyncCall<ResultT>(observable: Observable<ResultT>): ResultT {\n    let completed = false;\n    let result: ResultT | undefined = undefined;\n    let errorResult: Error | undefined = undefined;\n    // Perf note: this is not using an observer object to avoid a performance penalty in RxJS.\n    // See https://github.com/ReactiveX/rxjs/pull/5646 for details.\n    observable.subscribe(\n      (x: ResultT) => (result = x),\n      (err: Error) => (errorResult = err),\n      () => (completed = true),\n    );\n\n    if (errorResult !== undefined) {\n      throw errorResult;\n    }","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/core/src/virtual-fs/host/sync.ts#L16-L52","documentation":"SyncDelegateHost wraps a Host and guarantees every operation completes synchronously. In the constructor it checks the delegate host's capabilities.synchronous flag and throws SynchronousDelegateExpectedException if the underlying host can only return Observables that may resolve asynchronously. This protects callers who expect plain return values rather than Observables.","triggerScenarios":"Constructing new SyncDelegateHost(delegate) with a host whose capabilities.synchronous is false or undefined — e.g. wrapping a plain Host<T> or SimpleMemoryHost instead of a sync-capable host.","commonSituations":"Passing the default async filesystem host to tooling that expects sync access (older Angular CLI schematics/utilities that used SyncDelegateHost), or forgetting to wrap a host in a sync adapter that reports synchronous: true.","solutions":["Use a host with capabilities.synchronous === true (e.g. CordHost backed by a sync host, or a host explicitly implementing the sync capability)","Implement capabilities.synchronous: true on your custom Host, ensuring all its Observable-returning methods actually emit synchronously (of(), not from(promise))","Use the async host directly and subscribe to the Observables instead of wrapping it in SyncDelegateHost"],"exampleFix":"// before\nconst host = new SyncDelegateHost(new SimpleMemoryHost());\n// after\nconst syncHost = new SimpleMemoryHost();\nsyncHost.capabilities.synchronous = true; // only if reads are truly sync\nconst host = new SyncDelegateHost(syncHost);","handlingStrategy":"validation","validationCode":"import { SyncDelegateHost } from '@angular-devkit/core/src/virtual-fs/host/sync';\nfunction assertSyncHost(host) {\n  if (!host.capabilities || host.capabilities.synchronous !== true) {\n    throw new Error('Host must report capabilities.synchronous === true');\n  }\n  return host;\n}\nconst host = new SyncDelegateHost(assertSyncHost(delegate));","typeGuard":"function isSyncCapable(host) {\n  return typeof host === 'object' && host !== null &&\n    host.capabilities?.synchronous === true;\n}","tryCatchPattern":"try {\n  const host = new SyncDelegateHost(delegate);\n} catch (e) {\n  if (e.constructor.name === 'SynchronousDelegateExpectedException') {\n    // fall back to async Host API\n  } else { throw e; }\n}","preventionTips":["Check capabilities.synchronous before wrapping any host in SyncDelegateHost","Prefer using the async Host API directly in new code (SyncDelegateHost is deprecated)","For custom hosts, only set synchronous: true if every method emits synchronously"],"tags":["angular-devkit","virtual-fs","async","host-capabilities"],"backgroundTag":"sync-host-expected-async-host-given","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}