{"record":{"id":"c253d099617906f1","repo":"angular/angular-cli","slug":"builder-is-not-a-builder","errorCode":null,"errorMessage":"Builder is not a builder","messagePattern":"Builder is not a builder","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/angular_devkit/architect/node/node-modules-architect-host.ts","lineNumber":281,"sourceCode":"    const projectName = typeof target === 'string' ? target : target.project;\n    const metadata = this.workspaceHost.getMetadata(projectName);\n\n    return metadata;\n  }\n\n  async loadBuilder(info: NodeModulesBuilderInfo): Promise<Builder> {\n    const builder = await getBuilder(info.import);\n\n    if (builder[BuilderSymbol]) {\n      return builder;\n    }\n\n    // Default handling code is for old builders that incorrectly export `default` with non-ESM module\n    if (builder?.default[BuilderSymbol]) {\n      return builder.default;\n    }\n\n    throw new Error('Builder is not a builder');\n  }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function getBuilder(builderPath: string): Promise<any> {\n  const builder = await import(builderPath);\n\n  return 'default' in builder ? builder.default : builder;\n}\n","sourceCodeStart":263,"sourceCodeEnd":291,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular_devkit/architect/node/node-modules-architect-host.ts#L263-L291","documentation":"loadBuilder imports a builder module and verifies it carries the internal BuilderSymbol marking a properly exported Angular builder (via createBuilder). If the imported module (or its default export) lacks this symbol, Architect rejects it with 'Builder is not a builder'.","triggerScenarios":"resolveBuilder/loadBuilder imports a builder path whose module exports a plain function, an object without the symbol, or a default export that is not the result of createBuilder().","commonSituations":"Builders written as plain exported functions instead of createBuilder(fn); bundling/transpilation that strips or mangles exports; CommonJS/ESM interop where default wraps the real export incorrectly; pointing at the wrong file (index vs implementation).","solutions":["Export the builder via createBuilder() and use `export default` in the builder's entry file","Check the builders.json implementation path resolves to the module that actually default-exports the createBuilder result","Rebuild the builder with a correct TS/bundler config (esModuleInterop, commonjs settings) so exports are preserved","Upgrade the builder package if it predates the createBuilder/BuilderSymbol contract"],"exampleFix":"// before\nexport function myBuilder(options, context) { ... }\n// after\nimport { createBuilder } from '@angular-devkit/architect';\nexport default createBuilder(myBuilder);","handlingStrategy":"type-guard","validationCode":"const mod = await import(builderPath);\nconst exp = mod?.default ?? mod;\nif (typeof exp !== 'function' || !exp[BuilderSymbol]) {\n  throw new Error(`${builderPath} does not default-export a createBuilder() result`);\n}","typeGuard":"function isBuilder(v) {\n  return typeof v === 'function' && v[BuilderSymbol] === true;\n}","tryCatchPattern":"try {\n  const builder = await host.loadBuilder(info);\n} catch (e) {\n  if (e.message === 'Builder is not a builder') {\n    console.error(`Wrap the export in createBuilder(): export default createBuilder(fn) in ${info.info?.implementation || 'the builder module'}`);\n  }\n  throw e;\n}","preventionTips":["Always export builders via `export default createBuilder(fn)`","Keep a smoke test that imports each builder module and asserts the BuilderSymbol","Check bundler/TS output (dist) preserves the default export and symbol","Pin a recent @angular-devkit/architect version compatible with your builder's export style"],"tags":["angular","architect","builder","esm-exports"],"backgroundTag":"builder-not-a-builder","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}