AlistGo/alist · error · ErrSignExpired

sign expired

Error message

sign expired

What it means

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.

Source

Thrown at pkg/sign/sign.go:11

package sign

import "errors"

type Sign interface {
	Sign(data string, expire int64) string
	Verify(data, sign string) error
}

var (
	ErrSignExpired   = errors.New("sign expired")
	ErrSignInvalid   = errors.New("sign invalid")
	ErrExpireInvalid = errors.New("expire invalid")
	ErrExpireMissing = errors.New("expire missing")
)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Fetch a fresh signed URL from the server (re-request the link through the API) instead of reusing an old one
  2. Increase the expire duration when generating signs if legitimate clients need longer
  3. Check server/client clock synchronization — a skewed clock can make fresh links appear expired

Example fix

// before
if err := signer.Verify(data, sign); err != nil { panic(err) } // stale link blows up

// after
if errors.Is(err, sign.ErrSignExpired) {
    sign = apiGetFreshSign(data) // re-sign then retry
}
err = signer.Verify(data, sign)
Defensive patterns

Strategy: retry

Try / catch

if err := signer.Verify(data, signStr); err != nil {
	if errors.Is(err, sign.ErrSignExpired) {
		signStr = getFreshSignFromServer(data)
		return signer.Verify(data, signStr)
	}
	return err
}

Prevention

When it happens

Trigger: Verifying a signed download/proxy URL after its embedded expire timestamp has passed (expires < time.Now().Unix() and expires != 0).

Common situations: 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.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/ced4bfdae97699a0. Report an issue: GitHub.