phacility/phabricator · warning · PhutilArgumentUsageException
When specifying %s or %s, you must specify both arguments to
Error message
When specifying %s or %s, you must specify both arguments to define the beginning and end of the billing range.
What it means
PhutilArgumentUsageException thrown by the phortune invoice workflow when exactly one of --last / --next is given without --auto-range. A billing range is a closed interval: --last is the beginning epoch and --next the end epoch, and supplying only one half is ambiguous, so the workflow refuses rather than invent the missing bound (an invented bound risks double-billing).
Source
Thrown at src/applications/phortune/management/PhabricatorPhortuneManagementInvoiceWorkflow.php:99
$console->writeOut(
"%s\n",
pht(
'Set current time to %s.',
phabricator_datetime(PhabricatorTime::getNow(), $viewer)));
$auto_range = $args->getArg('auto-range');
$last_arg = $args->getArg('last');
$next_arg = $args->getArg('next');
if (!$auto_range && !$last_arg && !$next_arg) {
throw new PhutilArgumentUsageException(
pht(
'Specify a billing range with %s and %s, or use %s.',
'--last',
'--next',
'--auto-range'));
} else if (!$auto_range & (!$last_arg || !$next_arg)) {
throw new PhutilArgumentUsageException(
pht(
'When specifying %s or %s, you must specify both arguments '.
'to define the beginning and end of the billing range.',
'--last',
'--next'));
} else if (!$auto_range && ($last_arg && $next_arg)) {
$last_time = $this->parseTimeArgument($args->getArg('last'));
$next_time = $this->parseTimeArgument($args->getArg('next'));
} else if ($auto_range && ($last_arg || $next_arg)) {
throw new PhutilArgumentUsageException(
pht(
'Use either %s or %s and %s to specify the '.
'billing range, but not both.',
'--auto-range',
'--last',
'--next'));
} else {
$trigger = $subscription->getTrigger();View on GitHub (pinned to 5720a38cfe)
Solutions
- Add the missing companion flag so both --last and --next are present.
- Compute the two epochs from the subscription's billing period boundaries before invoking.
- Prefer --auto-range when you just want the scheduled period and do not need custom bounds.
Example fix
# before $ ./bin/phortune invoice --subscription PHID-PSUB-1234abcd --last 1690000000 # after $ ./bin/phortune invoice --subscription PHID-PSUB-1234abcd --last 1690000000 --next 1692600000
Defensive patterns
Strategy: validation
Validate before calling
// Both halves of the interval must be present.
if (!$auto_range && ($last_epoch xor $next_epoch)) {
throw new InvalidArgumentException(
'Billing range is a closed interval: provide both --last and --next (or use --auto-range).');
} Prevention
- Generate --last/--next from one source (the subscription's billing period boundaries) so they are always emitted as a pair.
- Treat epochs as raw Unix timestamps; the workflow parses them via parseTimeArgument().
- The queued worker stores them as trigger.last-epoch / trigger.this-epoch — keep naming straight to avoid half-filled pairs.
When it happens
Trigger: Running `... --subscription <PHID> --last 1690000000` (no --next), or `... --next 1692600000` (no --last), each without --auto-range. The condition (!$auto_range && (!$last_arg || !$next_arg)) fires when either half is missing.
Common situations: Scripts templating only the 'since' epoch; operators assuming --next defaults to now; flag names confused with the trigger daemon's naming ('trigger.last-epoch' / 'trigger.this-epoch' in the queued task).
Related errors
- Specify which subscription to invoice with %s.
- Specify a billing range with %s and %s, or use %s.
- Use either %s or %s and %s to specify the billing range, but
- Unable to load subscription with PHID "%s".
- Unable to calculate %s, this subscription has not been sched
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/7f6c114bfeef839d.
Report an issue: GitHub.