{"record":{"id":"fd0c861703097eed","repo":"syncthing/syncthing","slug":"certificate-has-expired","errorCode":null,"errorMessage":"certificate has expired","messagePattern":"certificate has expired","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/api/api.go","lineNumber":1893,"sourceCode":"\n\tif leaf.Subject.String() != leaf.Issuer.String() || len(leaf.IPAddresses) != 0 {\n\t\t// The certificate is not self signed, or has IP attributes we don't\n\t\t// add, so we leave it alone.\n\t\treturn nil\n\t}\n\tif len(leaf.DNSNames) > 1 {\n\t\t// The certificate has more DNS SANs attributes than we ever add, so\n\t\t// we leave it alone.\n\t\treturn nil\n\t}\n\tif len(leaf.DNSNames) == 1 && leaf.DNSNames[0] != leaf.Issuer.CommonName {\n\t\t// The one SAN is different from the issuer, so it's not one of our\n\t\t// newer self signed certificates.\n\t\treturn nil\n\t}\n\n\tif leaf.NotAfter.Before(time.Now()) {\n\t\treturn errors.New(\"certificate has expired\")\n\t}\n\tif leaf.NotAfter.Before(time.Now().Add(30 * 24 * time.Hour)) {\n\t\treturn errors.New(\"certificate will soon expire\")\n\t}\n\n\t// On macOS, check for certificates issued on or after July 1st, 2019,\n\t// with a longer validity time than 825 days.\n\tcutoff := time.Date(2019, 7, 1, 0, 0, 0, 0, time.UTC)\n\tif build.IsDarwin &&\n\t\tleaf.NotBefore.After(cutoff) &&\n\t\tleaf.NotAfter.Sub(leaf.NotBefore) > 825*24*time.Hour {\n\t\treturn errors.New(\"certificate incompatible with macOS 10.15 (Catalina)\")\n\t}\n\n\treturn nil\n}\n\nfunc errorStringMap(errs map[string]error) map[string]*string {","sourceCodeStart":1875,"sourceCodeEnd":1911,"githubUrl":"https://github.com/syncthing/syncthing/blob/058bcd7334839663cf569501d3ac539034d45cb5/lib/api/api.go#L1875-L1911","documentation":"Raised by the self-signed HTTPS certificate sanity check in the REST API layer. After confirming the leaf certificate is Syncthing's own newer-style self-signed certificate (zero DNS SANs, or a single SAN equal to the issuer's CommonName), the code compares leaf.NotAfter to time.Now(); if the certificate validity has passed, it returns errors.New(\"certificate has expired\"). It signals that the GUI's TLS certificate is dead and must be regenerated before modern clients will trust the endpoint.","triggerScenarios":"The certificate-check function runs against the GUI's certificate.pem/https-cert.pem leaf: the cert is recognized as Syncthing-issued (SAN rules match) and leaf.NotAfter is before time.Now(). Typically after a long downtime or a system clock moved past the validity period.","commonSituations":"Devices that were offline or retired for longer than the certificate lifetime (e.g. a year+); VMs restored from an old snapshot with an expired cert; RTC battery failure pushing the clock forward.","solutions":["Stop Syncthing, delete the expired certificate and key in the config directory (https-cert.pem/https-key.pem or certificate.pem/key.pem), and restart to generate a fresh self-signed certificate.","Check the system clock (date, NTP status); if the clock is wrong, fix it before regenerating certificates.","Alternatively replace the self-signed certificate with a proper one via the GUI HTTPS settings if clients must not re-accept a new cert.","Re-accept the new certificate in the browser/API client afterwards, since the device identity may change if the API cert is also used for the device ID."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check expiry before starting the GUI / making requests:\nleaf, err := getLeafCert(certPath)\nif err == nil && leaf.NotAfter.Before(time.Now()) {\n    // regenerate certificate before use\n}","typeGuard":null,"tryCatchPattern":"if err := checkCertificate(cert); err != nil {\n    if strings.Contains(err.Error(), \"certificate has expired\") {\n        // regenerate cert (delete cert+key, restart) instead of failing\n    }\n}","preventionTips":["Monitor certificate NotAfter dates like any other TLS cert.","Keep host clocks NTP-synced so validity windows are evaluated correctly.","Regenerate certs during scheduled maintenance before they lapse."],"tags":["tls","certificate","https","gui","syncthing"],"backgroundTag":null,"analyzedSha":"058bcd7334839663cf569501d3ac539034d45cb5","analyzedAt":"2026-08-15T07:53:43.174Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}