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.

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.

Appendix: 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)