{"record":{"id":"f56ab070c1e62d4c","repo":"juicedata/juicefs","slug":"list-encode-file-failed-expect-key-s-but-got-s","errorCode":null,"errorMessage":"list encode file failed: expect key %s, but got %s","messagePattern":"list encode file failed: expect key (.+?), but got (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/objbench.go","lineNumber":985,"sourceCode":"\t\t\tfor i := 0; i < keyTotal; i++ {\n\t\t\t\tif objs[i].Key() != sortedKeys[i] {\n\t\t\t\t\treturn fmt.Errorf(\"the result for list is incorrect\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\trunCase(\"special key\", func(blob object.ObjectStorage) error {\n\t\tkey := \"测试编码文件\" + `{\"name\":\"juicefs\"}` + string('\\u001F') + \"%uFF081%uFF09.jpg\"\n\t\tdefer blob.Delete(ctx, key) //nolint:errcheck\n\t\tif err := blob.Put(ctx, key, bytes.NewReader([]byte(\"1\"))); err != nil {\n\t\t\treturn fmt.Errorf(\"put encode file failed: %s\", err)\n\t\t} else {\n\t\t\tif resp, _, _, err := blob.List(ctx, \"\", \"测试编码文件\", \"\", \"\", 1, true); err != nil && err != utils.ErrNotSUP {\n\t\t\t\treturn fmt.Errorf(\"list encode file failed %s\", err)\n\t\t\t} else if len(resp) == 1 && resp[0].Key() != key {\n\t\t\t\treturn fmt.Errorf(\"list encode file failed: expect key %s, but got %s\", key, resp[0].Key())\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\trunCase(\"put a big object\", func(blob object.ObjectStorage) error {\n\t\tfsize := 256 << 20\n\t\tbuffL := 4 << 20\n\t\tbuff := make([]byte, buffL)\n\t\tutils.RandRead(buff)\n\t\tcount := int(math.Floor(float64(fsize) / float64(buffL)))\n\t\tcontent := make([]byte, fsize)\n\t\tfor i := 0; i < count; i++ {\n\t\t\tcopy(content[i*buffL:(i+1)*buffL], buff)\n\t\t}\n\t\tif err := blob.Put(ctx, key, bytes.NewReader(content)); err != nil {\n\t\t\treturn err\n\t\t}","sourceCodeStart":967,"sourceCodeEnd":1003,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/cmd/objbench.go#L967-L1003","documentation":"When the special-key List succeeds and returns exactly one object, objbench verifies its key equals the original encoded key; a mismatch yields this message naming the expected and actual keys. It means the backend mangled the key (encoding/decoding bug) during put or list.","triggerScenarios":"`len(resp) == 1 && resp[0].Key() != key` in the special-key case — the stored key differs from the key that was put (e.g. double/under-escaping of '%uFF08', unicode, or \\u001F).","commonSituations":"Drivers that don't escape percent sequences in keys; backends that normalize unicode (NFC/NFD); proxies that decode URL-encoded characters in key paths.","solutions":["Compare the expected vs got keys in the message to identify which characters were mangled","Fix the driver's key escaping/unescaping logic","Check for proxies or backend settings that rewrite URL paths","Avoid percent-encoding normalization in the driver"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"resp, _, _, err := blob.List(ctx, \"\", \"测试编码文件\", \"\", \"\", 1, true)\nif err == nil && len(resp) == 1 && resp[0].Key() != expectedKey {\n    // key was mangled by driver or backend\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify driver key escaping round-trips (put then list returns identical key)","Check backend unicode normalization (NFC/NFD) behavior","Avoid intermediaries that decode percent-encodings in key paths"],"tags":["object-storage","encoding","key-mangling"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}