{"record":{"id":"136d713ce7072e88","repo":"phacility/phabricator","slug":"unexpected-value-s-in-s-rrule-property-expe","errorCode":null,"errorMessage":"Unexpected value \"%s\" in \"%s\" RRULE property: expected only integers.","messagePattern":"Unexpected value \"(.+?)\" in \"(.+?)\" RRULE property: expected only integers\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/calendar/parser/data/PhutilCalendarRecurrenceRule.php","lineNumber":293,"sourceCode":"\n    foreach ($dict as $key => $value) {\n      if (isset($int_values[$key])) {\n        // None of these values may be negative.\n        if (!preg_match('/^\\d+\\z/', $value)) {\n          throw new Exception(\n            pht(\n              'Unexpected value \"%s\" in \"%s\" RULE property: expected an '.\n              'integer.',\n              $value,\n              $key));\n        }\n        $dict[$key] = (int)$value;\n      }\n\n      if (isset($int_lists[$key])) {\n        foreach ($value as $k => $v) {\n          if (!preg_match('/^-?\\d+\\z/', $v)) {\n            throw new Exception(\n              pht(\n                'Unexpected value \"%s\" in \"%s\" RRULE property: expected '.\n                'only integers.',\n                $v,\n                $key));\n          }\n          $value[$k] = (int)$v;\n        }\n        $dict[$key] = $value;\n      }\n    }\n\n    return self::newFromDictionary($dict);\n  }\n\n  private static function getAllWeekdayConstants() {\n    return array_keys(self::getWeekdayIndexMap());\n  }","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/calendar/parser/data/PhutilCalendarRecurrenceRule.php#L275-L311","documentation":"In RRULE dictionary normalization, list-valued integer properties (BYSECOND, BYMINUTE, BYHOUR, BYMONTH, BYMONTHDAY, BYEARDAY, BYWEEKNO, BYSETPOS) require every element to match /^-?\\d+$/ - an optionally negative integer. Any non-numeric element (weekday token, decimal, empty string) throws.","triggerScenarios":"'BYMONTHDAY' => ['MO'] (weekday token in a numeric-only field), 'BYSETPOS' => ['1.5'], a trailing empty string from exploding '1,2,' on commas.","commonSituations":"Producers that put weekday tokens into numeric fields; naive explode() of ICS lists leaving empty elements; sign handling like '+1' (fails the regex since + is not allowed).","solutions":["Keep weekday tokens (SU..SA) only in BYDAY; numeric list fields accept bare integers only.","Normalize lists before use: array_map('trim', $list), strip '+' prefixes, drop empty elements.","Validate every element against ^-?\\d+$ and reject the RRULE (or drop the element) before calling newFromDictionary()."],"exampleFix":"// before\n$dict['BYMONTHDAY'] = array('+1', '');\n// after\n$dict['BYMONTHDAY'] = array(1);","handlingStrategy":"type-guard","validationCode":"$int_lists = array('BYSECOND','BYMINUTE','BYHOUR','BYMONTH',\n  'BYMONTHDAY','BYYEARDAY','BYWEEKNO','BYSETPOS');\nforeach ($int_lists as $k) {\n  if (!isset($dict[$k])) { continue; }\n  $clean = array();\n  foreach ((array)$dict[$k] as $v) {\n    $v = trim((string)$v);\n    if ($v !== '' && preg_match('/^-?\\d+$/', $v)) {\n      $clean[] = (string)(int)$v;\n    }\n  }\n  if ($clean) { $dict[$k] = $clean; } else { unset($dict[$k]); }\n}","typeGuard":"function isIntegerListValue($value) {\n  return is_array($value)\n    && count($value) > 0\n    && !array_filter($value, function ($v) {\n      return !preg_match('/^-?\\d+$/', trim((string)$v));\n     });\n}","tryCatchPattern":"try {\n  $rule = PhutilCalendarRecurrenceRule::newFromDictionary($dict);\n} catch (Exception $ex) {\n  phlog($ex->getMessage()); // names the bad element and property\n  continue;\n}","preventionTips":["Trim, drop empties, and strip '+' signs when exploding ICS lists.","Keep weekday tokens out of numeric list fields (they belong in BYDAY only).","Validate every list element, not just the first."],"tags":["phutil","calendar","rrule","validation","list-type-error"],"backgroundTag":"schema-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}