{"record":{"id":"ced4bfdae97699a0","repo":"AlistGo/alist","slug":"sign-expired","errorCode":null,"errorMessage":"sign expired","messagePattern":"sign expired","errorType":"http","errorClass":"ErrSignExpired","httpStatus":401,"severity":"error","filePath":"pkg/sign/sign.go","lineNumber":11,"sourceCode":"package sign\n\nimport \"errors\"\n\ntype Sign interface {\n\tSign(data string, expire int64) string\n\tVerify(data, sign string) error\n}\n\nvar (\n\tErrSignExpired   = errors.New(\"sign expired\")\n\tErrSignInvalid   = errors.New(\"sign invalid\")\n\tErrExpireInvalid = errors.New(\"expire invalid\")\n\tErrExpireMissing = errors.New(\"expire missing\")\n)\n","sourceCodeStart":1,"sourceCodeEnd":16,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/pkg/sign/sign.go#L1-L16","documentation":"ErrSignExpired from the sign package (HMACSign.Verify in pkg/sign/hmac.go): the signature carried a non-zero expiry timestamp that is now in the past, so the signed URL is no longer valid even though the HMAC itself may be correct.","triggerScenarios":"Verifying a signed download/proxy URL after its embedded expire timestamp has passed (expires < time.Now().Unix() and expires != 0).","commonSituations":"Client cached or bookmarked a signed direct link and uses it after the TTL; server/client clock skew; the link was generated with a very short expire by design.","solutions":["Fetch a fresh signed URL from the server (re-request the link through the API) instead of reusing an old one","Increase the expire duration when generating signs if legitimate clients need longer","Check server/client clock synchronization — a skewed clock can make fresh links appear expired"],"exampleFix":"// before\nif err := signer.Verify(data, sign); err != nil { panic(err) } // stale link blows up\n\n// after\nif errors.Is(err, sign.ErrSignExpired) {\n    sign = apiGetFreshSign(data) // re-sign then retry\n}\nerr = signer.Verify(data, sign)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := signer.Verify(data, signStr); err != nil {\n\tif errors.Is(err, sign.ErrSignExpired) {\n\t\tsignStr = getFreshSignFromServer(data)\n\t\treturn signer.Verify(data, signStr)\n\t}\n\treturn err\n}","preventionTips":["Never cache signed URLs longer than their TTL","Generate signs with an expire margin that covers worst-case client latency"],"tags":["signing","hmac","expiry","auth"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}