theonedev/onedev · error · ValidationException

Duplicate field: ${fieldName}

Error message

Duplicate field: ${fieldName}

What it means

validateFields builds a field map from FieldInstance objects; if two instances share the same field name (put returns a previous value), ValidationException 'Duplicate field: <name>' is thrown, then validateFieldMap runs on the deduplicated map.

Source

Thrown at server-core/src/main/java/io/onedev/server/model/support/issue/field/FieldUtils.java:215

		validateFieldNames(fieldSpecMap.keySet(), fieldMap.keySet());
		for (Map.Entry<String, List<String>> entry: fieldMap.entrySet()) {
			if (entry.getValue() != null) {
				FieldSpec fieldSpec = Preconditions.checkNotNull(fieldSpecMap.get(entry.getKey()));
				validateFieldValue(fieldSpec, entry.getKey(), entry.getValue());
			}
		}
	}
	
	public static void validateFields(Map<String, FieldSpec> fieldSpecs, List<FieldInstance> fields) {
		Map<String, List<String>> fieldMap = new HashMap<>();
		for (FieldInstance field: fields) {
			List<String> values;
			if (field.getValueProvider() instanceof SpecifiedValue)
				values = field.getValueProvider().getValue();
			else
				values = null;
			if (fieldMap.put(field.getName(), values) != null)
				throw new ValidationException("Duplicate field: " + field.getName());
		}
		validateFieldMap(fieldSpecs, fieldMap);
	}

	@SuppressWarnings("unchecked")
	public static Map<String, Object> getFieldValues(Subject subject, Project project, Map<String, Serializable> fieldEdits) {
		var settingService = OneDev.getInstance(SettingService.class);
		var issueSetting = settingService.getIssueSetting();
		Map<String, Object> fieldValues = new HashMap<>();
		for (Map.Entry<String, Serializable> entry : fieldEdits.entrySet()) {
			var fieldName = entry.getKey();
			var fieldSpec = issueSetting.getFieldSpec(fieldName);
			if (fieldSpec == null)
				throw new NotAcceptableException("Undefined field: " + fieldName);
			if (!SecurityUtils.canEditIssueField(subject, project, fieldName))
				throw new UnauthorizedException("No permission to edit field: " + fieldName);

			List<String> values = new ArrayList<>();

View on GitHub (pinned to d44925c47c)

Solutions

  1. Deduplicate the field list by name before calling validateFields
  2. Fix the client/form so each field appears only once
  3. Use a Map<String,List<String>> keyed by field name to collect values

Example fix

// before
fields.add(new FieldInstance("Priority", ...));
fields.add(new FieldInstance("Priority", ...)); // duplicate
// after
Map<String,FieldInstance> byName = new LinkedHashMap<>();
fields.forEach(f -> byName.putIfAbsent(f.getName(), f));
validateFields(fieldSpecs, new ArrayList<>(byName.values()));
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (FieldInstance f : fields)
    if (!seen.add(f.getName()))
        throw new IllegalStateException("Duplicate field: " + f.getName());

Prevention

When it happens

Trigger: Submitting a collection of FieldInstances containing the same field name twice, e.g. duplicate form inputs or an API payload repeating a field.

Common situations: Buggy client code appending a field per iteration; duplicated issue template entries; merge of two field lists without deduplication.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/41b5d5a7c17a7d11. Report an issue: GitHub.