phacility/phabricator · error · Exception

Field "corpus" must be non-empty.

Error message

Field "corpus" must be non-empty.

What it means

differential.parsecommitmessage takes the raw commit message in the corpus parameter and parses it into fields. The method rejects the call before parsing when corpus is null or a zero-length string, because an empty message can never yield field values or useful validation results.

Source

Thrown at src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php:37

  }

  protected function defineReturnType() {
    return 'nonempty dict';
  }

  protected function execute(ConduitAPIRequest $request) {
    $viewer = $this->getViewer();

    $parser = DifferentialCommitMessageParser::newStandardParser($viewer);

    $is_partial = $request->getValue('partial');
    if ($is_partial) {
      $parser->setRaiseMissingFieldErrors(false);
    }

    $corpus = $request->getValue('corpus');
    if ($corpus === null || !strlen($corpus)) {
      throw new Exception(pht('Field "corpus" must be non-empty.'));
    }
    $field_map = $parser->parseFields($corpus);

    $errors = $parser->getErrors();
    $xactions = $parser->getTransactions();

    $revision_id_value = idx(
      $field_map,
      DifferentialRevisionIDCommitMessageField::FIELDKEY);
    $revision_id_valid_domain = PhabricatorEnv::getProductionURI('');

    return array(
      'errors' => $errors,
      'fields' => $field_map,
      'revisionIDFieldInfo' => array(
        'value' => $revision_id_value,
        'validDomain' => $revision_id_valid_domain,
      ),

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Pass the full raw commit message text in corpus.
  2. Skip the call entirely when the message is empty; an empty corpus is never useful.
  3. If messages may be whitespace-only, trim first and treat an empty trimmed result as 'no message'.

Example fix

// before
$client->callMethodSynchronous('differential.parsecommitmessage', array(
  'corpus' => $message, // $message may be null or ''
));

// after
if ($message !== null && trim($message) !== '') {
  $result = $client->callMethodSynchronous(
    'differential.parsecommitmessage',
    array('corpus' => $message));
}
Defensive patterns

Strategy: validation

Validate before calling

if ($corpus === null || trim($corpus) === '') {
  // nothing to parse; skip the conduit call
  return array();
}
$result = $client->callMethodSynchronous(
  'differential.parsecommitmessage',
  array('corpus' => $corpus));

Type guard

function isNonEmptyCorpus($text) {
  return is_string($text) && strlen(trim($text)) > 0;
}

Try / catch

try {
  $parsed = $client->callMethodSynchronous(
    'differential.parsecommitmessage', $params);
} catch (ConduitClientException $ex) {
  if (strpos($ex->getMessage(), 'corpus') !== false) {
    // empty corpus: fix the caller, do not retry
  } else {
    throw $ex;
  }
}

Prevention

When it happens

Trigger: Calling differential.parsecommitmessage with corpus omitted, set to null, or set to '' — typically automation running over a commit whose message is empty, or code that reads the message from a file or stdin before the read finished.

Common situations: Hook scripts that run on merges with empty messages; async file reads where the message variable is still null at call time; ported scripts that assumed corpus was optional.

Related errors


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