t8y2/dbx · error

invalid lease continuation: %s

Error message

invalid lease continuation: %s

What it means

parseUnsignedLong parses the continuation token used to page through leases into a uint64. If the token string is not a valid base-10 unsigned 64-bit integer, it fails with this error. The continuation value is expected to be a raw lease ID emitted by a previous leaseList page, so this error means the token is malformed or was never a lease ID.

Source

Thrown at agents/drivers/etcd-go/lease.go:181

var errLeaseListDeadline = errors.New("ETCD_LEASE_LIST_TIMEOUT")

func isDeadlineError(err error) bool {
	return errors.Is(err, context.DeadlineExceeded) || status.Code(err) == codes.DeadlineExceeded
}

func isLeaseListFallbackError(err error) bool {
	if errors.Is(err, errLeaseListDeadline) || errors.Is(err, context.DeadlineExceeded) {
		return true
	}
	code := status.Code(err)
	return code == codes.Unimplemented || code == codes.DeadlineExceeded
}

func parseUnsignedLong(value string) (uint64, error) {
	parsed, err := strconv.ParseUint(value, 10, 64)
	if err != nil {
		return 0, fmt.Errorf("invalid lease continuation: %s", value)
	}
	return parsed, nil
}

func leasePageIDs(leaseIDs []uint64, afterLeaseID *uint64, fetchLimit int) []uint64 {
	sorted := make([]uint64, len(leaseIDs))
	copy(sorted, leaseIDs)
	sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })
	result := []uint64{}
	for _, id := range sorted {
		if afterLeaseID != nil && id <= *afterLeaseID {
			continue
		}
		if len(result) >= fetchLimit {
			break
		}
		result = append(result, id)
	}

View on GitHub (pinned to c0390bff16)

Solutions

  1. Pass back the continuation token exactly as returned by the previous leaseList page, unmodified.
  2. If constructing manually, supply a decimal string of a uint64 lease ID (e.g. "7587868030128843137").
  3. Strip any URL-encoding, quotes, or whitespace before parsing; base64-decode only if your wrapper layer encoded it.
  4. Restart pagination without a continuation token to fetch the first page, then resume with the fresh token.

Example fix

// before
parseUnsignedLong("page-2") // not a uint64
// after
parseUnsignedLong("7587868030128843137") // lease ID from previous page
Defensive patterns

Strategy: validation

Validate before calling

func validContinuation(token string) bool {
	if token == "" {
		return false
	}
	_, err := strconv.ParseUint(token, 10, 64)
	return err == nil
}
// if afterLeaseID != "" && !validContinuation(afterLeaseID) { reject before calling leaseList }

Try / catch

resp, err := driver.LeaseList(continuation)
if err != nil {
	if strings.HasPrefix(err.Error(), "invalid lease continuation") {
		// token unusable: restart pagination from the first page
		resp, err = driver.LeaseList("")
	}
	if err != nil {
		return err
	}
}

Prevention

When it happens

Trigger: leaseList called with an afterLeaseID/continuation string that is empty, contains non-digit characters, has a sign or decimal point, exceeds uint64 range, or is an opaque/op-echo token from a different API.

Common situations: Client stored the continuation as a JSON object or base64 and passed the whole blob back; truncation/URL-encoding corrupted the token; passing a key or revision instead of a lease ID as the continuation; cross-driver paging tokens mixed up.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/3fb5fb6692fefe36. Report an issue: GitHub.