phacility/phabricator · warning · PhutilArgumentUsageException

Unable to parse time "%s".

Error message

Unable to parse time "%s".

What it means

A PhutilArgumentUsageException from PhabricatorManagementWorkflow::parseTimeArgument(), the shared helper management workflows use for time options like --since. An empty value returns null, but any non-empty value that strtotime() fails to parse (or that resolves to an epoch <= 0, i.e. on or before 1970-01-01) throws.

Source

Thrown at src/infrastructure/management/PhabricatorManagementWorkflow.php:23

  public function isExecutable() {
    return true;
  }

  public function getViewer() {
    // Some day, we might provide a more general viewer mechanism to scripts.
    // For now, workflows can call this method for convenience and future
    // flexibility.
    return PhabricatorUser::getOmnipotentUser();
  }

  protected function parseTimeArgument($time) {
    if (!strlen($time)) {
      return null;
    }

    $epoch = strtotime($time);
    if ($epoch <= 0) {
      throw new PhutilArgumentUsageException(
        pht('Unable to parse time "%s".', $time));
    }
    return $epoch;
  }

  protected function newContentSource() {
    return PhabricatorContentSource::newForSource(
      PhabricatorConsoleContentSource::SOURCECONST);
  }

  protected function logInfo($label, $message) {
    $this->logRaw(
      tsprintf(
        "**<bg:blue> %s </bg>** %s\n",
        $label,
        $message));
  }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Use an unambiguous machine format strtotime() always accepts, such as '2025-01-31' or '2025-01-31 14:30:00'
  2. Use supported relative expressions exactly: '-30 days', 'now', 'yesterday'
  3. Quote the argument so the shell does not mangle it, and check the variable is non-empty and typo-free in your script

Example fix

# before
$ bin/worker --since "yesteday"

# after
$ bin/worker --since "2025-01-01" 
# or
$ bin/worker --since "-30 days"
Defensive patterns

Strategy: validation

Validate before calling

// Mirror parseTimeArgument()'s rules before passing a CLI value.
function parseTimeOrExit($time) {
  if (!strlen($time)) { return null; }
  $epoch = strtotime($time);
  if ($epoch === false || $epoch <= 0) {
    fwrite(STDERR, "Unparseable time: {$time}\n");
    exit(1);
  }
  return $epoch;
}

Type guard

function isValidPhabricatorTime($time) {
  if (!strlen($time)) { return true; } // empty is allowed -> null
  $epoch = strtotime($time);
  return $epoch !== false && $epoch > 0;
}

Try / catch

try { $since = $workflow->parseTimeArgument($raw); } catch (PhutilArgumentUsageException $ex) { /* print message, show correct date examples, exit non-zero */ }

Prevention

When it happens

Trigger: Passing a relative date with a typo (e.g. 'yesteday'), a locale-specific format strtotime() does not understand (e.g. '01/02/2025' ambiguity, '2025-13-45'), or a date before the Unix epoch; passing the literal string '0' or 'false' which strtotime maps to epoch 0.

Common situations: Shell scripts interpolating empty or malformed variables into --since/--until options; automation passing ISO dates with a 'Z' suffix on old strtotime() behavior; users typing natural-language dates the parser rejects.

Understand the failure class

Related errors


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