{"record":{"id":"75d0314d1f2f8686","repo":"google-gemini/gemini-cli","slug":"invalid-retention-period-format-period-expect","errorCode":null,"errorMessage":"Invalid retention period format: ${period}. Expected format: <number><unit> where unit is h, d, w, or m","messagePattern":"Invalid retention period format: (.+?)\\. Expected format: <number><unit> where unit is h, d, w, or m","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/utils/sessionCleanup.ts","lineNumber":392,"sourceCode":"      }\n    }\n\n    if (shouldDelete) {\n      sessionsToDelete.push(entry);\n    }\n  }\n\n  return sessionsToDelete;\n}\n\n/**\n * Parses retention period strings like \"30d\", \"7d\", \"24h\" into milliseconds\n * @throws {Error} If the format is invalid\n */\nfunction parseRetentionPeriod(period: string): number {\n  const match = period.match(/^(\\d+)([dhwm])$/);\n  if (!match) {\n    throw new Error(\n      `Invalid retention period format: ${period}. Expected format: <number><unit> where unit is h, d, w, or m`,\n    );\n  }\n\n  const value = parseInt(match[1], 10);\n  const unit = match[2];\n\n  // Reject zero values as they're semantically invalid\n  if (value === 0) {\n    throw new Error(\n      `Invalid retention period: ${period}. Value must be greater than 0`,\n    );\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion\n  return value * MULTIPLIERS[unit as keyof typeof MULTIPLIERS];\n}\n","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/cli/src/utils/sessionCleanup.ts#L374-L410","documentation":"Thrown by parseRetentionPeriod when a retention-period string does not match the regex /^(\\d+)([dhwm])$/ — i.e. it is not <digits> followed by exactly one of h/d/w/m. Used by the session cleanup feature to convert human-friendly periods (e.g. 30d, 24h) into milliseconds via MULTIPLIERS.","triggerScenarios":"parseRetentionPeriod(period) receives a string failing the regex: contains letters other than the unit (e.g. '30 days'), wrong unit (e.g. '30s'), non-numeric value (e.g. 'abc'), missing unit (e.g. '30'), extra characters, or whitespace.","commonSituations":"User sets a cleanup retention config value like '30 days' or '1 month' (full word) instead of '30d'/'1m'. Typos such as '30D' (uppercase not matched) or '30day'. Empty string. Value loaded from a config file with surrounding quotes or whitespace.","solutions":["Use the exact format <number><unit> with a lowercase unit: h, d, w, or m — e.g. '24h', '30d', '2w', '6m'.","Trim/normalize the value before passing it; ensure no surrounding whitespace or quotes.","If exposing this in a UI, validate against the same regex and reject invalid input before saving."],"exampleFix":"// before\n// retention: '30 days'\n\n// after\n// retention: '30d'","handlingStrategy":"validation","validationCode":"function isValidRetentionPeriod(period) {\n  return /^(\\d+)([dhwm])$/.test(period);\n}\n// Use before storing/applying the value.\nif (!isValidRetentionPeriod(userInput)) {\n  throw new Error('Retention must be like 24h, 30d, 2w, or 6m');\n}","typeGuard":"const isRetentionPeriodString = (v) =>\n  typeof v === 'string' && /^(\\d+)([dhwm])$/.test(v);","tryCatchPattern":null,"preventionTips":["Validate retention strings at the config-load boundary with the same regex.","Provide a dropdown of valid units in any UI that collects retention."],"tags":["session-cleanup","config","validation","regex","parsing"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}