phacility/phabricator · error · Exception

Field label "%s" is parsed by two custom fields: "%s" and "%

Error message

Field label "%s" is parsed by two custom fields: "%s" and "%s". Each label must be parsed by only one field.

What it means

DifferentialCommitMessageParser::getLabelMap() builds a normalized label-to-field-key map from every enabled commit-message field, using each field's getFieldAliases() plus getFieldName(). If two enabled fields claim the same normalized label, commit-message parsing would be ambiguous, so the parser throws with the label and both conflicting field keys. This is a configuration/extension conflict that surfaces the first time the parser is used after the conflicting field is enabled.

Source

Thrown at src/applications/differential/parser/DifferentialCommitMessageParser.php:369

  }


/* -(  Internals  )---------------------------------------------------------- */


  private function getLabelMap() {
    if ($this->labelMap === null) {
      $field_list = $this->getCommitMessageFields();

      $label_map = array();
      foreach ($field_list as $field_key => $field) {
        $labels = $field->getFieldAliases();
        $labels[] = $field->getFieldName();

        foreach ($labels as $label) {
          $normal_label = self::normalizeFieldLabel($label);
          if (!empty($label_map[$normal_label])) {
            throw new Exception(
              pht(
                'Field label "%s" is parsed by two custom fields: "%s" and '.
                '"%s". Each label must be parsed by only one field.',
                $label,
                $field_key,
                $label_map[$normal_label]));
          }

          $label_map[$normal_label] = $field_key;
        }
      }

      $this->labelMap = $label_map;
    }

    return $this->labelMap;
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Read the message: it names the label and both field keys; rename one field's getFieldName() or prune its getFieldAliases() so no label overlaps
  2. Disable one of the two conflicting fields in the custom-field configuration if both are not needed
  3. If your custom field intentionally mirrors a core label, override getFieldAliases() to return array() and give it a unique field name
  4. After fixing, clear caches (phabricator/ $ ./bin/cache purge) because the enabled field list is cached

Example fix

// before (custom field duplicating a core label)
class MyProjectCustomField extends DifferentialCommitMessageCustomField {
  public function getFieldName() { return pht('Reviewers'); }
  public function getFieldAliases() { return array('Reviewed By'); }
}

// after
public function getFieldName() { return pht('Project Reviewers'); }
public function getFieldAliases() { return array(); }
Defensive patterns

Strategy: validation

Validate before calling

// After changing custom-field config, smoke-test parsing before use:
phabricator/ $ ./bin/cache purge
phabricator/ $ echo 'Reviewed By: alice' | ./bin/differential ... # any path that parses a commit message
// Duplicate-label conflicts throw immediately, so this surfaces the config error safely.

Type guard

// Config-time check: no two enabled fields share a normalized label
function assertNoLabelConflicts(array $fields) {
  $seen = array();
  foreach ($fields as $key => $field) {
    $labels = array_merge($field->getFieldAliases(), array($field->getFieldName()));
    foreach ($labels as $label) {
      $n = strtolower(preg_replace('/[^a-z0-9]/i', '', $label));
      if (isset($seen[$n])) {
        throw new Exception("Label conflict: {$key} vs {$seen[$n]} on '{$label}'");
      }
      $seen[$n] = $key;
    }
  }
}

Prevention

When it happens

Trigger: Enabling a custom field whose field name or an alias normalizes to the same label as a core field (e.g., two fields claiming 'Reviewers' or 'Reviewed By'); a custom field subclass that does not override getFieldAliases() and inherits a parent's labels; label normalization collapsing case/punctuation differences ('Reviewer' vs 'reviewer:'); upgrading an extension that adds new aliases

Common situations: Adding third-party custom fields through PhabricatorCustomFieldConfigOption; local extensions cloned from core field classes; enabling two similar extensions after a Phabricator upgrade; cached field lists making the conflict appear only after cache clearing.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/9071454b8baf8236. Report an issue: GitHub.