apache/flink · error · InvalidSemanticAnnotationException
Target field {} was added twice.
Error message
Target field {} was added twice. What it means
Thrown by SingleInputSemanticProperties.addForwardedField(int sourceField, int targetField) when the targetField position has already been registered as a forwarded target from any source field. The method enforces that each output field is forwarded from exactly one input field; a second mapping to the same target is a contradictory semantic annotation.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/common/operators/SingleInputSemanticProperties.java:86
@Override
public FieldSet getReadFields(int input) {
if (input != 0) {
throw new IndexOutOfBoundsException();
}
return this.readFields;
}
/**
* Adds, to the existing information, a field that is forwarded directly from the source
* record(s) to the destination record(s).
*
* @param sourceField the position in the source record(s)
* @param targetField the position in the destination record(s)
*/
public void addForwardedField(int sourceField, int targetField) {
if (isTargetFieldPresent(targetField)) {
throw new InvalidSemanticAnnotationException(
"Target field " + targetField + " was added twice.");
}
FieldSet targetFields = fieldMapping.get(sourceField);
if (targetFields != null) {
fieldMapping.put(sourceField, targetFields.addField(targetField));
} else {
fieldMapping.put(sourceField, new FieldSet(targetField));
}
}
private boolean isTargetFieldPresent(int targetField) {
for (FieldSet targetFields : fieldMapping.values()) {
if (targetFields.contains(targetField)) {
return true;
}
}
return false;View on GitHub (pinned to 2f3c205e92)
Solutions
- Review the function's @ForwardedField annotations and ensure each target field index appears in exactly one annotation.
- If a field is genuinely computed (not forwarded), remove it from @ForwardedField annotations.
- If you are manually building SingleInputSemanticProperties, check isTargetFieldPresent(targetField) before calling addForwardedField, or audit the fieldMapping for duplicate targets.
- Use @ForwardedFields with correct source->target position expressions.
Example fix
// before
@ForwardedField("0->1; 2->1") // ERROR: target field 1 twice
public static class MyMapper extends RichMapFunction<Tuple3<String, Integer, String>, Tuple2<String, Integer>> {
public Tuple2<String, Integer> map(Tuple3<String, Integer, String> in) { ... }
}
// after
@ForwardedField("0->1")
public static class MyMapper extends RichMapFunction<Tuple3<String, Integer, String>, Tuple2<String, Integer>> {
public Tuple2<String, Integer> map(Tuple3<String, Integer, String> in) { ... }
} Defensive patterns
Strategy: validation
Validate before calling
void safeAddForwardedField(SingleInputSemanticProperties props, int source, int target) {
if (props instanceof SingleInputSemanticProperties.AllFieldsForwardedProperties) return;
// Check if target is already claimed by another source
for (int s = 0; s < 256; s++) {
if (s != source && props.getForwardingTargetFields(0, s).contains(target)) {
throw new IllegalStateException("Target field " + target + " already forwarded from source " + s);
}
}
props.addForwardedField(source, target);
} Type guard
boolean isTargetAvailable(SingleInputSemanticProperties props, int targetField) {
return props.getForwardingSourceField(0, targetField) == -1;
} Try / catch
try {
props.addForwardedField(sourceField, targetField);
} catch (InvalidSemanticAnnotationException e) {
// duplicate target field annotation; review @ForwardedField annotations
throw new RuntimeException("Duplicate @ForwardedField target: " + e.getMessage(), e);
} Prevention
- Audit @ForwardedField annotations to ensure each target position appears exactly once.
- Use a helper that checks getForwardingSourceField before addForwardedField.
- Write unit tests that validate semantic property consistency before job submission.
When it happens
Trigger: Manually calling addForwardedField(0, 1) followed by addForwardedField(2, 1) on the same SingleInputSemanticProperties instance. Using duplicate or overlapping @ForwardedField annotations on a function that the compiler translates into addForwardedField calls.
Common situations: Incorrect @ForwardedField annotations on a MapFunction or FlatMapFunction where two input fields are annotated as forwarding to the same output position. Copy-paste errors when annotating a rich function's semantic properties. Misunderstanding positional semantics of forwarded fields.
Related errors
- Cannot modify forwarded fields
- The runtime context has not been initialized yet. Try access
- The broadcast input name may not be null.
- The broadcast input root operator may not be null.
- Cannot execute operator {}
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/076f837617afe5a0.
Report an issue: GitHub.