phacility/phabricator · error · Exception

Commit message field "%s" was expected to render a string or

Error message

Commit message field "%s" was expected to render a string or null value, but rendered a "%s" instead.

What it means

differential.getcommitmessage iterates the commit-message field list and calls renderFieldValue($wire_value) on each field. The API contract requires every field to render either a string or null; if any field implementation returns another type (int, array, bool, object), the method throws a plain Exception naming the field key and the offending gettype(). This is a server-side invariant violation, almost always introduced by a custom commit-message field.

Source

Thrown at src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php:108

      // from, so we hit the same validation logic for values which came over
      // the wire and which we generated.
      $field_value = $field->readFieldValueFromConduit($field_value);

      $value_map[$field_key] = $field_value;
    }

    $key_title = DifferentialTitleCommitMessageField::FIELDKEY;

    $commit_message = array();
    foreach ($field_list as $field_key => $field) {
      $label = $field->getFieldName();
      $wire_value = $value_map[$field_key];
      $value = $field->renderFieldValue($wire_value);

      $is_template = ($is_create && $field->isTemplateField());

      if (!is_string($value) && !is_null($value)) {
        throw new Exception(
          pht(
            'Commit message field "%s" was expected to render a string or '.
            'null value, but rendered a "%s" instead.',
            $field->getFieldKey(),
            gettype($value)));
      }

      $is_title = ($field_key == $key_title);

      if ($value === null || !strlen($value)) {
        if ($is_template) {
          $commit_message[] = $label.': ';
        }
      } else {
        if ($is_title) {
          $commit_message[] = $value;
        } else {
          $value = str_replace(

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Find the offending field: the exception text names the field key - match it against your custom field FIELDKEY constants
  2. Fix renderFieldValue to return a string or null; format non-string data (implode arrays, cast scalars) before returning
  3. Return null for 'nothing to render' instead of false or an empty array
  4. Temporarily disable the custom field to confirm the diagnosis, then re-enable after the fix

Example fix

// before (custom field)
public function renderFieldValue($value) {
  return $value; // may be int or array -> crashes getcommitmessage
}

// after
public function renderFieldValue($value) {
  if ($value === null) {
    return null;
  }
  if (is_array($value)) {
    return implode(', ', $value);
  }
  return (string)$value;
}
Defensive patterns

Strategy: type-guard

Type guard

// Guard inside every custom commit-message field.
public function renderFieldValue($value) {
  if ($value === null) {
    return null;
  }
  if (!is_string($value)) {
    if (is_array($value)) {
      $value = implode(', ', $value);
    } else {
      $value = (string)$value;
    }
  }
  return $value;
}

Try / catch

// Server-side wrapper while diagnosing a misbehaving field:
$value = $field->renderFieldValue($wire_value);
if (!is_string($value) && !is_null($value)) {
  phlog(pht('Field %s rendered %s; suppressing.',
    $field->getFieldKey(), gettype($value)));
  $value = null;
}

Prevention

When it happens

Trigger: Installing a custom Differential commit-message field (or an extension overriding renderFieldValue) that returns an integer, array, or boolean - for example returning a raw epoch timestamp or a list of reviewers instead of a formatted string. Every getcommitmessage call then fails for revisions using that field.

Common situations: Site administrators adding custom fields for release notes or reviewer lines; fields written for the object-rendering API where arrays are fine, reused for commit messages where they are not; upstream field regressions after an upgrade.

Related errors


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