{"record":{"id":"289950c36c887040","repo":"angular/angular","slug":"invalid-function-call-it-should-have-only-a-singl","errorCode":null,"errorMessage":"Invalid function call: It should have only a single object literal argument, but contained ${args.length}.","messagePattern":"Invalid function call: It should have only a single object literal argument, but contained (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/compiler-cli/linker/src/file_linker/file_linker.ts","lineNumber":65,"sourceCode":"  /**\n   * Link the metadata extracted from the args of a call to a partial declaration function.\n   *\n   * The `declarationScope` is used to determine the scope and strategy of emission of the linked\n   * definition and any shared constant statements.\n   *\n   * @param declarationFn the name of the function used to declare the partial declaration - e.g.\n   *     `ɵɵngDeclareDirective`.\n   * @param args the arguments passed to the declaration function, should be a single object that\n   *     corresponds to the `R3DeclareDirectiveMetadata` or `R3DeclareComponentMetadata` interfaces.\n   * @param declarationScope the scope that contains this call to the declaration function.\n   */\n  linkPartialDeclaration(\n    declarationFn: string,\n    args: TExpression[],\n    declarationScope: DeclarationScope<TConstantScope, TExpression>,\n  ): TExpression {\n    if (args.length !== 1) {\n      throw new Error(\n        `Invalid function call: It should have only a single object literal argument, but contained ${args.length}.`,\n      );\n    }\n\n    const metaObj = AstObject.parse<R3PartialDeclaration, TExpression>(\n      args[0],\n      this.linkerEnvironment.host,\n    );\n    const ngImport = metaObj.getNode('ngImport');\n    const emitScope = this.getEmitScope(ngImport, declarationScope);\n\n    const minVersion = metaObj.getString('minVersion');\n    const version = metaObj.getString('version');\n    const linker = this.linkerSelector.getLinker(declarationFn, minVersion, version);\n    const definition = linker.linkPartialDeclaration(emitScope.constantPool, metaObj, version);\n\n    return emitScope.translateDefinition(definition);\n  }","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/compiler-cli/linker/src/file_linker/file_linker.ts#L47-L83","documentation":"FileLinker.linkPartialDeclaration requires ɵɵngDeclare* calls to receive exactly one argument: the object literal holding R3DeclareDirectiveMetadata / R3DeclareComponentMetadata (and friends). Zero or multiple arguments means the call is not compiler-generated output, and the linker throws with the actual argument count.","triggerScenarios":"Hand-written `ɵɵngDeclareDirective()` with no args or extra args; a user-defined wrapper that coincidentally uses the reserved ɵɵngDeclare* name and passes extra parameters; broken codegen splitting the metadata object.","commonSituations":"Application code defining functions named ɵɵngDeclareDirective/Component/Injectable; post-processing that rewrites declaration calls; monkey-patched library bundles.","solutions":["Never define, wrap, or rename functions with the reserved ɵɵngDeclare* names","Recompile the library with the official Angular compiler","Remove post-processing steps that rewrite these call expressions"],"exampleFix":"// before\nconst declare = ɵɵngDeclareDirective;\ndeclare(MyDir, { selector: '[x]' });\n// after\nɵɵngDeclareDirective({ minVersion: '14.1', ngImport: core, type: MyDir, selector: '[x]' });","handlingStrategy":"type-guard","validationCode":"import * as t from '@babel/types';\nconst isPartialDeclarationCall = (node: t.Node): node is t.CallExpression =>\n  t.isCallExpression(node) &&\n  t.isIdentifier(node.callee) && /^ɵɵngDeclare/.test(node.callee.name) &&\n  node.arguments.length === 1 && t.isObjectExpression(node.arguments[0]);","typeGuard":"const isWellFormedDeclarationCall = (node: t.CallExpression): boolean =>\n  t.isIdentifier(node.callee) && /^ɵɵngDeclare/.test(node.callee.name) &&\n  node.arguments.length === 1 && t.isObjectExpression(node.arguments[0]);","tryCatchPattern":null,"preventionTips":["Never define or wrap functions named ɵɵngDeclare* yourself","Recompile the library with the official Angular compiler","Avoid post-processing that rewrites declaration calls"],"tags":["angular-linker","partial-compilation","arity","reserved-name"],"backgroundTag":"invalid-declaration-metadata","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}