{"record":{"id":"32371f1fa1c34e32","repo":"oven-sh/bun","slug":"cert-not-yet-valid","errorCode":null,"errorMessage":"CERT_NOT_YET_VALID","messagePattern":"CERT_NOT_YET_VALID","errorType":"error_code","errorClass":"CertError","httpStatus":null,"severity":"error","filePath":"src/http/error.rs","lineNumber":139,"sourceCode":"#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error, strum::IntoStaticStr)]\npub enum CertError {\n    #[error(\"OK\")]\n    OK,\n    #[error(\"UNABLE_TO_GET_ISSUER_CERT\")]\n    UNABLE_TO_GET_ISSUER_CERT,\n    #[error(\"UNABLE_TO_GET_CRL\")]\n    UNABLE_TO_GET_CRL,\n    #[error(\"UNABLE_TO_DECRYPT_CERT_SIGNATURE\")]\n    UNABLE_TO_DECRYPT_CERT_SIGNATURE,\n    #[error(\"UNABLE_TO_DECRYPT_CRL_SIGNATURE\")]\n    UNABLE_TO_DECRYPT_CRL_SIGNATURE,\n    #[error(\"UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY\")]\n    UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,\n    #[error(\"CERT_SIGNATURE_FAILURE\")]\n    CERT_SIGNATURE_FAILURE,\n    #[error(\"CRL_SIGNATURE_FAILURE\")]\n    CRL_SIGNATURE_FAILURE,\n    #[error(\"CERT_NOT_YET_VALID\")]\n    CERT_NOT_YET_VALID,\n    #[error(\"CERT_HAS_EXPIRED\")]\n    CERT_HAS_EXPIRED,\n    #[error(\"CRL_NOT_YET_VALID\")]\n    CRL_NOT_YET_VALID,\n    #[error(\"CRL_HAS_EXPIRED\")]\n    CRL_HAS_EXPIRED,\n    #[error(\"ERROR_IN_CERT_NOT_BEFORE_FIELD\")]\n    ERROR_IN_CERT_NOT_BEFORE_FIELD,\n    #[error(\"ERROR_IN_CERT_NOT_AFTER_FIELD\")]\n    ERROR_IN_CERT_NOT_AFTER_FIELD,\n    #[error(\"ERROR_IN_CRL_LAST_UPDATE_FIELD\")]\n    ERROR_IN_CRL_LAST_UPDATE_FIELD,\n    #[error(\"ERROR_IN_CRL_NEXT_UPDATE_FIELD\")]\n    ERROR_IN_CRL_NEXT_UPDATE_FIELD,\n    #[error(\"OUT_OF_MEM\")]\n    OUT_OF_MEM,\n    #[error(\"DEPTH_ZERO_SELF_SIGNED_CERT\")]","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/http/error.rs#L121-L157","documentation":"X509 verify result 9 (X509_V_ERR_CERT_NOT_YET_VALID): the certificate's notBefore (validity start) is in the future relative to the local clock, so the cert is not yet valid. Mapped via get_cert_error_from_no (src/http/lib.rs:1528) to CertError::CERT_NOT_YET_VALID, message \"certificate is not yet valid\" (FetchTasklet.rs:1397).","triggerScenarios":"fetch/https/Bun.connect TLS handshake where the peer cert (or an intermediate) has notBefore > current system time — usually wrong local clock rather than a bad cert.","commonSituations":"Containers/VMs booted with a stale or skewed clock (no NTP), Raspberry Pi without RTC battery, laptops resumed from suspend with drifted time, or certs issued seconds ago against a clock a few minutes behind.","solutions":["Sync the system clock (timedatectl set-ntp true / restart chrony or ntpd; restart the container/VM if it inherited a bad clock)","Confirm the skew: date -u && curl -sI https://example.com | grep -i date","If the cert genuinely starts in the future (CA clock skew), wait until the notBefore time passes and retry","For lab environments only, bypass with fetch(url, { tls: { rejectUnauthorized: false } }) while the clock is fixed"],"exampleFix":"# diagnose skew\ndate -u\nsudo timedatectl set-ntp true   # fix clock, then retry","handlingStrategy":"validation","validationCode":"function clockIsPlausible(maxSkewMs = 5 * 60_000): boolean {\n  return Math.abs(Date.now() - expectedWallClockMs()) <= maxSkewMs;\n}\n// cheap check: compare against a trusted local source, e.g. an NTP-adjusted time service,\n// before firing TLS-heavy batch jobs\nif (!clockIsPlausible()) throw new Error(\"System clock skewed — fix NTP before TLS calls\");","typeGuard":"function isCertErrorCode(e: unknown, code = \"CERT_NOT_YET_VALID\"): e is Error & { code: string } {\n  return e instanceof Error && (e as any).code === code;\n}","tryCatchPattern":"try {\n  await fetch(url);\n} catch (e) {\n  if (isCertErrorCode(e, \"CERT_NOT_YET_VALID\")) {\n    // usually local clock skew: alert ops to fix NTP instead of disabling verification\n    throw new Error(\"Peer certificate not yet valid — check system clock/NTP\");\n  }\n  throw e;\n}","preventionTips":["Enable NTP/chrony on all hosts and containers; verify with timedatectl in provisioning","Run date -u sanity checks at job startup for long-lived daemons on VMs that suspend","Don't disable verification to 'fix' clock problems — fix the clock"],"tags":["tls","certificates","clock","fetch","environment"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}