angular/angular · error · FatalDiagnosticError
DUPLICATE_BINDING_NAME
DUPLICATE_BINDING_NAME
Error message
Input '${bindingPropertyName}' is bound to both '${firstMember.name}' and '${member.name}'. What it means
Thrown when two inputs in the same directive/component resolve to the same binding property name. After each member's InputMapping is computed, its bindingPropertyName (alias if given, else the member name) is tracked in a Map; a repeat raises DUPLICATE_BINDING_NAME with `Input 'x' is bound to both 'first' and 'second'`, plus related information pointing at the first declaration. Ambiguous template bindings cannot be emitted, so compilation stops.
Source
Thrown at packages/compiler-cli/src/ngtsc/annotations/directive/src/shared.ts:1452
const inputMapping = tryParseInputFieldMapping(
clazz,
member,
evaluator,
reflector,
importTracker,
isCore,
refEmitter,
compilationMode,
emitDeclarationOnly,
);
if (inputMapping === null) {
continue;
}
const bindingPropertyName = inputMapping.bindingPropertyName;
if (bindings.has(bindingPropertyName)) {
const firstMember = bindings.get(bindingPropertyName)!;
throw new FatalDiagnosticError(
ErrorCode.DUPLICATE_BINDING_NAME,
member.node ?? clazz,
`Input '${bindingPropertyName}' is bound to both '${firstMember.name}' and '${member.name}'.`,
[makeRelatedInformation(firstMember.node ?? clazz, `The first binding is declared here.`)],
);
}
bindings.set(bindingPropertyName, member);
if (member.isStatic) {
throw new FatalDiagnosticError(
ErrorCode.INCORRECTLY_DECLARED_ON_STATIC_MEMBER,
member.node ?? clazz,
`Input "${member.name}" is incorrectly declared as static member of "${clazz.name.text}".`,
);
}
// Validate that signal inputs are not accidentally declared in the `inputs` metadata.
if (inputMapping.isSignal && Object.hasOwn(inputsFromClassDecorator, classPropertyName)) {View on GitHub (pinned to 51cb07e980)
Solutions
- Make every binding property name unique — rename or drop one alias: `@Input('firstLabel') firstName` / `@Input('lastLabel') lastName`.
- Check the `inputs: ['alias: prop']` metadata array for entries duplicating a decorated member's name or alias.
- Use the related-information location in the diagnostic to find the first binding and fix the second.
Example fix
// before
@Input('label') firstName = '';
@Input('label') lastName = '';
// after
@Input('firstLabel') firstName = '';
@Input('lastLabel') lastName = ''; Defensive patterns
Strategy: validation
Validate before calling
// collect input binding names per class and fail on duplicates
function checkDuplicateInputAliases(members: {prop: string; alias?: string}[]) {
const seen = new Map<string, string>();
for (const m of members) {
const binding = m.alias ?? m.prop;
if (seen.has(binding)) {
throw new Error(`Input '${binding}' bound to both '${seen.get(binding)}' and '${m.prop}'`);
}
seen.set(binding, m.prop);
}
} Prevention
- Keep a per-class inventory of input binding names (aliases included) when adding or renaming inputs.
- Cross-check the `inputs: ['alias: prop']` metadata array against decorated members.
- Use the diagnostic's related information to jump to the first conflicting binding.
When it happens
Trigger: `@Input('label') labelA = ''; @Input('label') labelB = '';` — or an alias colliding with another member's plain name: `@Input() label = ''; @Input('label') other = '';`.
Common situations: Copy-pasted aliased inputs; renames that accidentally create alias/name collisions; entries in the class-decorator `inputs: ['alias: prop']` metadata array overlapping a decorated member's name; merging two components.
Related errors
- INCORRECTLY_DECLARED_ON_STATIC_MEMBER
- INITIALIZER_API_DISALLOWED_MEMBER_VISIBILITY
- VALUE_HAS_WRONG_TYPE
- VALUE_HAS_WRONG_TYPE
- LOCAL_COMPILATION_UNRESOLVED_CONST
AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22).
Data as JSON: /api/errors/f8ef147435c8feb4.
Report an issue: GitHub.