pulumi/pulumi · error · Error
Component '${componentName}' constructor 'args' parameter mu
Error message
Component '${componentName}' constructor 'args' parameter must have a type What it means
Beyond being named `args`, the parameter must carry an explicit type annotation so the analyzer can inspect the args interface via the TypeScript checker. An untyped (implicitly any) parameter gives the checker nothing to enumerate into schema properties.
Source
Thrown at sdk/nodejs/provider/experimental/analyzer.ts:317
private analyzeComponent(node: typescript.ClassDeclaration): ComponentDefinition {
const componentName = node.name?.text!;
// We expect exactly 1 constructor, and it must have and 'args'
// parameter that has an interface type.
const constructors = node.members.filter((member: typescript.ClassElement) =>
ts.isConstructorDeclaration(member),
) as typescript.ConstructorDeclaration[];
if (constructors.length !== 1) {
throw new Error(`Component '${componentName}' must have exactly one constructor`);
}
const argsParam = constructors?.[0].parameters.find((param: typescript.ParameterDeclaration) => {
return ts.isIdentifier(param.name) && param.name.escapedText === "args";
});
if (!argsParam) {
throw new Error(`Component '${componentName}' constructor must have an 'args' parameter`);
}
if (!argsParam.type) {
throw new Error(`Component '${componentName}' constructor 'args' parameter must have a type`);
}
const args = this.checker.getTypeAtLocation(argsParam.type);
const argsSymbol = args.getSymbol();
if (!argsSymbol || !isInterface(argsSymbol)) {
throw new Error(`Component '${componentName}' constructor 'args' parameter must be an interface`);
}
let inputs: Record<string, PropertyDefinition> = {};
// Use args.getProperties() instead of argsSymbol.members to include
// properties inherited from extended interfaces.
const argsProperties = args.getProperties();
if (argsProperties.length > 0) {
inputs = this.analyzeSymbols(
{ component: componentName, inputOutput: InputOutput.Neither, typeName: argsSymbol.getName() },
argsProperties,
);
}
View on GitHub (pinned to 793f7b2e16)
Solutions
- Add an explicit interface type to the args parameter
- Define the inputs as an exported interface (e.g. `interface MyComponentArgs {...}`) and annotate the parameter with it
- Enable noImplicitAny to catch this at compile time
Example fix
// before
constructor(args) { ... }
// after
constructor(args: MyComponentArgs) { ... } Defensive patterns
Strategy: type-guard
Validate before calling
function argsParamTyped(c: any): boolean { const m = c.toString().match(/constructor\(\s*args\s*\)\s*{/); return !m; } Type guard
function hasTypedArgs<T extends new (args: I) => any, I>(c: T): c is T { return true; } Prevention
- Enable noImplicitAny in tsconfig
- Always annotate args with an interface type
- Never use `any` for component args
When it happens
Trigger: Declaring `constructor(args)` or `constructor(args: any)` with no concrete interface type annotation.
Common situations: Quick prototypes without typed args; implicit-any codebases without strict checking.
Related errors
- Component '${componentName}' must have exactly one construct
- Component '${componentName}' constructor must have an 'args'
- Component '${componentName}' constructor 'args' parameter mu
- Class or interface has no name: ${this.formatErrorContext(co
- ${leakMessage}
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/26d50af4f43a7495.
Report an issue: GitHub.