AlistGo/alist · error · ErrExpireInvalid

expire invalid

Error message

expire invalid

What it means

ErrExpireInvalid from HMACSign.Verify: the trailing segment of the sign string (after the last ':') was parsed with strconv.ParseInt and failed, so the signature cannot carry a valid expiry timestamp.

Source

Thrown at pkg/sign/sign.go:13

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. Only pass sign strings produced by HMACSign.Sign, which appends ":<unix-seconds>"
  2. If generating signs externally, format the expiry as base10 Unix seconds in the final segment
  3. URL-encode the sign value when transporting it in a query so separators survive

Example fix

// before
sign := "c2lnbmF0dXJlOmFiYw==" // no numeric expiry segment

// after
sign := hmacSign.NewHMACSign(secret).Sign(data, time.Now().Add(time.Hour).Unix())
// -> "<base64url-hmac>:1700000000"
Defensive patterns

Strategy: validation

Validate before calling

parts := strings.Split(signStr, ":")
if _, err := strconv.ParseInt(parts[len(parts)-1], 10, 64); err != nil {
	return errors.New("sign string lacks a numeric expiry segment")
}

Prevention

When it happens

Trigger: Verify receives a sign whose last ':'-separated segment is not a decimal Unix timestamp — e.g. "abc" instead of "1700000000", or an empty-but-present segment that still fails parsing.

Common situations: Sign strings produced by a different implementation, hand-crafted signatures, or the sign being split/rejoined incorrectly when passing through query parameters.

Related errors


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