{"record":{"id":"f98cea5ae35650c7","repo":"phacility/phabricator","slug":"period-specified-with-days-must-be-at-least-1","errorCode":null,"errorMessage":"Period specified with --days must be at least 1.","messagePattern":"Period specified with --days must be at least 1\\.","errorType":"console","errorClass":"PhutilArgumentUsageException","httpStatus":null,"severity":"warning","filePath":"src/applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php","lineNumber":31,"sourceCode":"      ->setArguments(\n        array(\n          array(\n            'name'    => 'days',\n            'param'   => 'days',\n            'default' => 30,\n            'help'    => pht(\n              'Number of days back (default 30).'),\n          ),\n        ));\n  }\n\n  public function execute(PhutilArgumentParser $args) {\n    $console = PhutilConsole::getConsole();\n    $viewer = $this->getViewer();\n\n    $days = (int)$args->getArg('days');\n    if ($days < 1) {\n      throw new PhutilArgumentUsageException(\n        pht(\n          'Period specified with --days must be at least 1.'));\n    }\n\n    $duration = phutil_units(\"{$days} days in seconds\");\n\n    $since = (PhabricatorTime::getNow() - $duration);\n    $until = PhabricatorTime::getNow();\n\n    $mails = id(new PhabricatorMetaMTAMailQuery())\n      ->setViewer($viewer)\n      ->withDateCreatedBetween($since, $until)\n      ->execute();\n\n    $unfiltered = array();\n    $delivered = array();\n\n    foreach ($mails as $mail) {","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php#L13-L49","documentation":"`bin/mail volume` reports mail volume over a window ending now; `--days` is cast to int and must be >= 1, otherwise PhutilArgumentUsageException. Because the cast happens first, non-numeric strings and empty values become 0 and also fail. The value feeds phutil_units(\"N days in seconds\"), which is why 0/negative is rejected.","triggerScenarios":"`--days 0`, `--days -7`, `--days abc`, or `--days ''` (all cast to an int < 1).","commonSituations":"Automation passing an unset variable as the days value; operators assuming 0 means 'today' (it does not — use --days 1).","solutions":["Use a positive integer: `bin/mail volume --days 30`.","For a single day, pass `--days 1`.","Validate/cast the value to a positive int in scripts before invoking."],"exampleFix":"// before\n$ bin/mail volume --days abc\n// Exception: Period specified with --days must be at least 1.\n\n// after\n$ bin/mail volume --days 30","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Mirror the workflow's cast-then-compare rule:\nfunction is_valid_volume_days($value) {\n  return (int)$value >= 1;\n}\nif (!is_valid_volume_days($days)) {\n  fwrite(STDERR, \"--days must be an integer >= 1.\\n\");\n  exit(1);\n}","tryCatchPattern":null,"preventionTips":["Use positive integers; '0' does not mean today — use 1.","Validate the value in scripts after the int cast.","Default the variable to 30 rather than leaving it unset."],"tags":["php","phabricator","cli","argument-validation","metrics"],"backgroundTag":"invalid-cli-argument","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}