{"record":{"id":"94a677057109ab01","repo":"jackwener/OpenCLI","slug":"gmail-label-had-an-invalid-timestamp","errorCode":null,"errorMessage":"Gmail ${label} had an invalid timestamp","messagePattern":"Gmail (.+?) had an invalid timestamp","errorType":"error_code","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/gmail/utils.js","lineNumber":55,"sourceCode":"}\n\nexport function parseAccount(raw) {\n  const value = raw ?? 0;\n  const account = Number(value);\n  if (!Number.isInteger(account) || account < 0 || account > 20) {\n    throw new ArgumentError('account must be an integer between 0 and 20');\n  }\n  return account;\n}\n\nfunction cleanString(value) {\n  return typeof value === 'string' ? value.trim() : '';\n}\n\nfunction gmailDate(value, label) {\n  let timestamp = Number(value);\n  if (!Number.isFinite(timestamp) || timestamp <= 0) {\n    throw new CommandExecutionError(`Gmail ${label} had an invalid timestamp`);\n  }\n  if (timestamp < 10_000_000_000) timestamp *= 1000;\n  if (timestamp > 10_000_000_000_000) timestamp /= 1000;\n  const date = new Date(timestamp);\n  if (Number.isNaN(date.getTime())) {\n    throw new CommandExecutionError(`Gmail ${label} had an invalid timestamp`);\n  }\n  return date.toISOString();\n}\n\nfunction decodeEntities(value) {\n  return String(value || '')\n    .replace(/&nbsp;/gi, ' ')\n    .replace(/&amp;/gi, '&')\n    .replace(/&lt;/gi, '<')\n    .replace(/&gt;/gi, '>')\n    .replace(/&quot;/gi, '\"')\n    .replace(/&#39;|&apos;/gi, \"'\")","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/gmail/utils.js#L37-L73","documentation":"gmailDate converts Gmail's numeric timestamps into ISO strings. If the value cannot be coerced into a finite positive number (NaN, 0, negative, or a garbage string), the library throws CommandExecutionError because a valid timestamp is required to build the date. This is the pre-normalization branch of the check.","triggerScenarios":"The browser capture returns a missing/empty date field, a string like 'N/A' or an already-formatted date string ('2024-01-01T...'), or 0/negative epoch values from a malformed batch view or fetch payload.","commonSituations":"Gmail DOM changes altering what the bridge scrapes; truncated captures dropping the timestamp field; callers feeding preformatted date strings where epoch millis are expected; new/unread items with placeholder timestamps.","solutions":["Inspect the capture payload (entry.responsePreview) to see what timestamp value was actually received.","Update the scraper/bridge if Gmail's DOM changed and the wrong element is being captured.","Ensure timestamps are supplied as epoch seconds or milliseconds, not preformatted date strings.","Retry the fetch; a truncated or partial capture may be the cause."],"exampleFix":"// before\n{ date: '2024-06-01 12:00' } // string, not epoch\n// after\n{ date: 1717243200 } // epoch seconds","handlingStrategy":"type-guard","validationCode":"const ts = Number(value);\nif (!Number.isFinite(ts) || ts <= 0) {\n  throw new Error(`expected epoch seconds/millis, got ${JSON.stringify(value)}`);\n}","typeGuard":"function isEpochTimestamp(v) {\n  const n = Number(v);\n  return Number.isFinite(n) && n > 0;\n}","tryCatchPattern":"try {\n  const iso = gmailDate(value, 'search');\n} catch (e) {\n  if (/invalid timestamp/.test(e.message)) {\n    console.warn('Skipping row with bad timestamp:', value);\n    return null; // skip instead of failing the batch\n  }\n  throw e;\n}","preventionTips":["Ensure the scraper captures the epoch field, not a formatted date string.","Log raw payloads when a row fails so bad values are visible.","Test against Gmail DOM changes that can alter which node is scraped.","Filter or default rows lacking timestamps before processing."],"tags":["gmail","timestamp","data-format"],"backgroundTag":"invalid-timestamp","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}