juicedata/juicefs · error

invalid key %s, fail to parse timestamp

Error message

invalid key %s, fail to parse timestamp

What it means

Companion to the previous check: the key split into two parts, but the second part (the timestamp that decides when delayed deletions become eligible for cleanup) is not a valid base-10 integer. Cleanup aborts because it cannot decide whether the slices are due for deletion.

Source

Thrown at pkg/meta/redis.go:4120

	var rs []*redis.IntCmd
	for key := range delKeys {
		var clean bool
		task := func(tx *redis.Tx) error {
			ss = ss[:0]
			rs = rs[:0]
			val, err := tx.HGet(ctx, m.delSlices(), key).Result()
			if err == redis.Nil {
				return nil
			} else if err != nil {
				return err
			}
			ps := strings.Split(key, "_")
			if len(ps) != 2 {
				return fmt.Errorf("invalid key %s", key)
			}
			ts, err := strconv.ParseInt(ps[1], 10, 64)
			if err != nil {
				return fmt.Errorf("invalid key %s, fail to parse timestamp", key)
			}

			m.decodeDelayedSlices([]byte(val), &ss)
			clean, err = scan(ss, ts)
			if err != nil {
				return err
			}
			if clean {
				_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
					for _, s := range ss {
						rs = append(rs, pipe.HIncrBy(ctx, m.sliceRefs(), m.sliceKey(s.Id, s.Size), -1))
					}
					pipe.HDel(ctx, m.delSlices(), key)
					id, err := strconv.ParseUint(ps[0], 10, 64)
					if err != nil {
						return fmt.Errorf("invalid key %s, fail to parse slice id", key)
					}
					m.genLog(ctx, pipe, time.Now(), "CLEANUP_TRASH_SLICES(%d,%d)", id, ts)

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Print the key (it is included in the error) and inspect the actual hash entry with redis-cli.
  2. Fix or remove the malformed key if its data is not needed, then re-run cleanup.
  3. Audit what writes into the delSlices hash — ensure no other app or old client shares this Redis DB.
  4. Restore affected hash entries from a known-good metadata backup if corruption is widespread.
Defensive patterns

Strategy: validation

Validate before calling

for _, k := range hashKeys {
    ps := strings.Split(k, "_")
    if len(ps) == 2 { if _, err := strconv.ParseInt(ps[1], 10, 64); err != nil { fmt.Printf("bad timestamp in key %q\n", k) } }
}

Try / catch

if err := cleanup(ctx); err != nil && strings.Contains(err.Error(), "fail to parse timestamp") {
    logger.Errorf("corrupt delSlices key: %v", err)
    // remove or repair the specific key reported, then re-run
}

Prevention

When it happens

Trigger: A delSlices hash key like "12345_notanumber" — produced by manual edits, corrupted metadata, or a mismatched writer — encountered while parsing the timestamp portion during delayed-slice cleanup.

Common situations: Hand-edited Redis keys; partially restored backups; another application writing colliding keys into the same hash.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/68b824ef8d88984b. Report an issue: GitHub.