{"record":{"id":"a629ee1ec29c2813","repo":"phacility/phabricator","slug":"relative-ttl-must-not-be-more-than-s-seconds-b","errorCode":null,"errorMessage":"Relative TTL must not be more than \"%s\" seconds, but TTL \"%s\" was specified.","messagePattern":"Relative TTL must not be more than \"(.+?)\" seconds, but TTL \"(.+?)\" was specified\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/files/storage/PhabricatorFile.php","lineNumber":1505,"sourceCode":"          pht(\n            'Absolute TTL must be in the present or future, but TTL \"%s\" '.\n            'is in the past.',\n            $absolute_ttl));\n      }\n\n      $this->setTtl($absolute_ttl);\n    } else if ($relative_ttl !== null) {\n      if ($relative_ttl < 0) {\n        throw new Exception(\n          pht(\n            'Relative TTL must be zero or more seconds, but \"%s\" is '.\n            'negative.',\n            $relative_ttl));\n      }\n\n      $max_relative = phutil_units('365 days in seconds');\n      if ($relative_ttl > $max_relative) {\n        throw new Exception(\n          pht(\n            'Relative TTL must not be more than \"%s\" seconds, but TTL '.\n            '\"%s\" was specified.',\n            $max_relative,\n            $relative_ttl));\n      }\n\n      $absolute_ttl = PhabricatorTime::getNow() + $relative_ttl;\n\n      $this->setTtl($absolute_ttl);\n    }\n\n    $view_policy = idx($params, 'viewPolicy');\n    if ($view_policy) {\n      $this->setViewPolicy($params['viewPolicy']);\n    }\n\n    $is_explicit = (idx($params, 'isExplicitUpload') ? 1 : 0);","sourceCodeStart":1487,"sourceCodeEnd":1523,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/files/storage/PhabricatorFile.php#L1487-L1523","documentation":"A relative TTL was supplied that exceeds the hard cap of phutil_units('365 days in seconds') = 31,536,000 seconds. Phabricator limits relative TTLs to one year so that callers do not silently create effectively-permanent files; anything longer must be expressed as an absolute 'ttl.absolute' epoch timestamp (still in the present or future).","triggerScenarios":"PhabricatorFile::newFromParams() with 'ttl.relative' => 40000000 (or 366 days, '2 years', etc.). The check runs after the negative check, so any relative value in (31536000, INF) throws with both the cap and the offending value in the message.","commonSituations":"Product specs asking for retention of 18 months or 2 years implemented as relative seconds; multiplying days by the wrong factor (e.g. 365 * 24 * 60 computed as 525,600 minutes passed as if seconds); copying a milliseconds value (a year in ms is 3.15e10) into the field.","solutions":["For expiries beyond one year, convert to an absolute timestamp: 'ttl.absolute' => PhabricatorTime::getNow() + $seconds (with $seconds still checked to be future).","For expiries within a year, cap the relative value at 31536000 or recompute it from the real deadline.","Double-check the unit: the field is seconds, not minutes, hours, or milliseconds."],"exampleFix":"// before\n$params = array(\n  'ttl.relative' => 2 * 365 * 86400, // 63,072,000 > cap\n);\n\n// after\n$params = array(\n  'ttl.absolute' => PhabricatorTime::getNow() + (2 * 365 * 86400),\n);","handlingStrategy":"validation","validationCode":"$max_relative = phutil_units('365 days in seconds');\nif (idx($params, 'ttl.relative', 0) > $max_relative) {\n  // long expiries must be absolute\n  $params['ttl.absolute'] = PhabricatorTime::getNow() + $params['ttl.relative'];\n  unset($params['ttl.relative']);\n}","typeGuard":"function isWithinRelativeTtlCap($seconds): bool {\n  return is_int($seconds) && $seconds >= 0 && $seconds <= phutil_units('365 days in seconds');\n}","tryCatchPattern":null,"preventionTips":["Remember the field unit is seconds and the cap is 31,536,000 (365 days).","For multi-year retention, store a deadline and convert to 'ttl.absolute' yourself.","Centralize TTL computation in one helper so the cap is enforced in one place."],"tags":["phabricator","file-storage","ttl","range-error","php"],"backgroundTag":"value-out-of-range","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}