{"record":{"id":"68b824ef8d88984b","repo":"juicedata/juicefs","slug":"invalid-key-s-fail-to-parse-timestamp","errorCode":null,"errorMessage":"invalid key %s, fail to parse timestamp","messagePattern":"invalid key (.+?), fail to parse timestamp","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/redis.go","lineNumber":4120,"sourceCode":"\tvar rs []*redis.IntCmd\n\tfor key := range delKeys {\n\t\tvar clean bool\n\t\ttask := func(tx *redis.Tx) error {\n\t\t\tss = ss[:0]\n\t\t\trs = rs[:0]\n\t\t\tval, err := tx.HGet(ctx, m.delSlices(), key).Result()\n\t\t\tif err == redis.Nil {\n\t\t\t\treturn nil\n\t\t\t} else if err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tps := strings.Split(key, \"_\")\n\t\t\tif len(ps) != 2 {\n\t\t\t\treturn fmt.Errorf(\"invalid key %s\", key)\n\t\t\t}\n\t\t\tts, err := strconv.ParseInt(ps[1], 10, 64)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"invalid key %s, fail to parse timestamp\", key)\n\t\t\t}\n\n\t\t\tm.decodeDelayedSlices([]byte(val), &ss)\n\t\t\tclean, err = scan(ss, ts)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif clean {\n\t\t\t\t_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {\n\t\t\t\t\tfor _, s := range ss {\n\t\t\t\t\t\trs = append(rs, pipe.HIncrBy(ctx, m.sliceRefs(), m.sliceKey(s.Id, s.Size), -1))\n\t\t\t\t\t}\n\t\t\t\t\tpipe.HDel(ctx, m.delSlices(), key)\n\t\t\t\t\tid, err := strconv.ParseUint(ps[0], 10, 64)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"invalid key %s, fail to parse slice id\", key)\n\t\t\t\t\t}\n\t\t\t\t\tm.genLog(ctx, pipe, time.Now(), \"CLEANUP_TRASH_SLICES(%d,%d)\", id, ts)","sourceCodeStart":4102,"sourceCodeEnd":4138,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/redis.go#L4102-L4138","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hand-edited Redis keys; partially restored backups; another application writing colliding keys into the same hash.","solutions":["Print the key (it is included in the error) and inspect the actual hash entry with redis-cli.","Fix or remove the malformed key if its data is not needed, then re-run cleanup.","Audit what writes into the delSlices hash — ensure no other app or old client shares this Redis DB.","Restore affected hash entries from a known-good metadata backup if corruption is widespread."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for _, k := range hashKeys {\n    ps := strings.Split(k, \"_\")\n    if len(ps) == 2 { if _, err := strconv.ParseInt(ps[1], 10, 64); err != nil { fmt.Printf(\"bad timestamp in key %q\\n\", k) } }\n}","typeGuard":null,"tryCatchPattern":"if err := cleanup(ctx); err != nil && strings.Contains(err.Error(), \"fail to parse timestamp\") {\n    logger.Errorf(\"corrupt delSlices key: %v\", err)\n    // remove or repair the specific key reported, then re-run\n}","preventionTips":["Validate hash key format after metadata restores","Restrict Redis access to JuiceFS only","Compare suspect keys against keys written by a healthy instance"],"tags":["redis","key-format","timestamp","delayed-slices"],"backgroundTag":"invalid-date-format","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}