phacility/phabricator · error · Exception

Unable to construct a date value from value of type "%s".

Error message

Unable to construct a date value from value of type "%s".

What it means

AphrontFormDateControlValue::newFromWild() is the loose constructor used when a date arrives from storage or an untrusted source. It accepts exactly two shapes: an array dictionary (as produced by the date control request reader, keys like 'd'/'t'/'e') or anything is_numeric() (an epoch or numeric string). Any other value — a formatted string like '2026-01-01', null, a boolean, an object — throws, with the PHP type name included in the message.

Source

Thrown at src/view/form/control/AphrontFormDateControlValue.php:146

      $value->valueDate,
      $value->valueTime);

    if ($formatted) {
      list($value->valueDate, $value->valueTime) = $formatted;
    }

    $value->valueEnabled = idx($dictionary, 'e');

    return $value;
  }

  public static function newFromWild(PhabricatorUser $viewer, $wild) {
    if (is_array($wild)) {
      return self::newFromDictionary($viewer, $wild);
    } else if (is_numeric($wild)) {
      return self::newFromEpoch($viewer, $wild);
    } else {
      throw new Exception(
        pht(
          'Unable to construct a date value from value of type "%s".',
          gettype($wild)));
    }
  }

  public function getDictionary() {
    return array(
      'd' => $this->valueDate,
      't' => $this->valueTime,
      'e' => $this->valueEnabled,
    );
  }

  public function getValueAsFormat($format) {
    return phabricator_format_local_time(
      $this->getEpoch(),
      $this->viewer,

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Convert strings to epochs first: newFromEpoch($viewer, strtotime($date_string)).
  2. If the value comes from the date control form submission, use newFromRequest($request, $key) or newFromDictionary() instead of newFromWild().
  3. Validate or coerce unknown input (is_array / is_numeric) before calling newFromWild().

Example fix

// before
$value = AphrontFormDateControlValue::newFromWild($viewer, '2026-01-01');

// after
$value = AphrontFormDateControlValue::newFromEpoch(
  $viewer,
  strtotime('2026-01-01'));
Defensive patterns

Strategy: validation

Validate before calling

if (!is_array($raw) && !is_numeric($raw)) {
  $raw = strtotime((string)$raw); // or reject the input explicitly
}
$value = AphrontFormDateControlValue::newFromWild($viewer, $raw);

Type guard

function isWildDateInput($value) {
  return is_array($value) || is_numeric($value);
}

Try / catch

try {
  $value = AphrontFormDateControlValue::newFromWild($viewer, $raw);
} catch (Exception $ex) {
  // Unparseable stored value: fall back to the current epoch.
  $value = AphrontFormDateControlValue::newFromEpoch(
    $viewer,
    PhabricatorTime::getNow());
}

Prevention

When it happens

Trigger: Passing a human-readable date string ('2026-01-01', 'Jan 1 2026'), null, false, or an object to newFromWild($viewer, $value).

Common situations: Custom storage or Conduit endpoints that keep dates as formatted strings; migrating legacy string date columns into date controls; default values pulled from config where the value is null.

Related errors


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