Replacing file link with another file via `rename` results in `Input/output error` if link with the same path was unlinked before
Author: Slava0135Created Sep 3, 2026Updated Sep 3, 2026
Labelskind/bug
What happened:
Hello I am running some tests for different filesystems, including juicefs. There seems to be a following issue when using FUSE (POSIX) interface and SQLite metadata storage:
- Create an empty file
file1. - Create (hard) link from
file1atlink. - Unlink
link. - Create an empty file
file2. - Create (hard) link from
file1atlinkagain. - Try to rename
file2tolink.
Last operation fails with Input/output error.
Mount log reports internal error (file locations from 1.5.0-dev+2026-09-03.f2f31b6f):
2026/09/03 07:52:57.157083 juicefs[1495] <ERROR>: error: UNIQUE constraint failed: jfs_edge.parent, jfs_edge.name
goroutine 368 [running]:
runtime/debug.Stack()
/usr/lib/go-1.26/src/runtime/debug/stack.go:26 +0x5e
github.com/juicedata/juicefs/pkg/meta.errno({0x50a4f00, 0x3eb4c02bd770})
/root/juicefs-git/pkg/meta/utils.go:157 +0x16e
github.com/juicedata/juicefs/pkg/meta.(*dbMeta).doRename(0x3eb4bf766ac0, {0x512b240, 0x3eb4bf9a9040}, 0x1, {0x3eb4c01d8b14, 0x5}, 0x1, {0x3eb4c01d8b1c, 0x4}, 0x0, ...)
/root/juicefs-git/pkg/meta/sql.go:2663 +0x448
github.com/juicedata/juicefs/pkg/meta.(*baseMeta).Rename(0x3eb4bf369408, {0x512b240, 0x3eb4bf9a9040}, 0x1, {0x3eb4c01d8b14, 0x5}, 0x1, {0x3eb4c01d8b1c, 0x4}, 0x0, ...)
/root/juicefs-git/pkg/meta/base.go:1965 +0x90d
github.com/juicedata/juicefs/pkg/vfs.(*VFS).Rename(0x3eb4c02c1360, {0x512de60, 0x3eb4bf9a9040}, 0x1, {0x3eb4c01d8b14, 0x5}, 0x1, {0x3eb4c01d8b1c, 0x4}, 0x0)
/root/juicefs-git/pkg/vfs/vfs.go:374 +0x2fc
github.com/juicedata/juicefs/pkg/fuse.(*fileSystem).Rename(0x3eb4c056c0a0, 0x4a639d?, 0x3eb4bf7c86c0, {0x3eb4c01d8b14, 0x5}, {0x3eb4c01d8b1c, 0x4})
/root/juicefs-git/pkg/fuse/fuse.go:165 +0xd1
github.com/hanwen/go-fuse/v2/fuse.doRename(0x3eb4c02f2f00, 0x3eb4bf71a488)
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/opcode.go:487 +0xf4
github.com/hanwen/go-fuse/v2/fuse.init.1.func1(0x1a00000068?, 0x2?)
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/opcode.go:810 +0x43
github.com/hanwen/go-fuse/v2/fuse.(*Server).handleRequest(0x3eb4c02f2f00, 0x3eb4bf71a488)
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/server.go:821 +0x2f1
github.com/hanwen/go-fuse/v2/fuse.(*Server).loop(0x3eb4c02f2f00, 0x1)
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/server.go:794 +0x110
created by github.com/hanwen/go-fuse/v2/fuse.(*Server).readRequest in goroutine 1
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/server.go:451 +0x668 [[email protected]:157]What you expected to happen:
Last operation is expected to finish successfully.
How to reproduce it (as minimally and precisely as possible):
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
int status;
status = creat("file1", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
printf("CREAT: %d\n", status);
close(status);
status = link("file1", "link");
printf("LINK: %d\n", status);
status = unlink("link");
printf("UNLINK: %d\n", status);
status = creat("file2", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
printf("CREAT: %d\n", status);
close(status);
status = link("file1", "link");
printf("LINK: %d\n", status);
status = rename("file2", "link");
printf("RENAME: %d (%s)\n", status, strerror(errno));
}
// ::Expected::
// CREAT: 3
// LINK: 0
// UNLINK: 0
// CREAT: 3
// LINK: 0
// RENAME: 0 (Success)
// ::Actual::
// CREAT: 3
// LINK: 0
// UNLINK: 0
// CREAT: 3
// LINK: 0
// RENAME: -1 (Input/output error)Steps:
- Create a new juicefs filesystem in standalone mode with SQLite metadata storage.
- Mount the filesystem.
- Compile the test and run it inside filesystem root.
- Observe that last operation fails with error.
Anything else we need to know?
Full command output:
root@ubuntu:/# ~/juicefs-git/juicefs format sqlite3://fstest.db fstest
2026/09/03 07:49:57.899113 juicefs[1453] <INFO>: Meta address: sqlite3://fstest.db [[email protected]:655]
2026/09/03 07:49:57.900858 juicefs[1453] <INFO>: Data use file:///var/jfs/fstest/ [[email protected]:584]
2026/09/03 07:49:57.904053 juicefs[1453] <INFO>: Volume is formatted as {
"Name": "fstest",
"UUID": "351aef67-786f-431e-82f3-28da539acb17",
"Storage": "file",
"Tiers": {
"0": {
"ID": 0,
"StorageClass": "",
"Tag": ""
}
},
"Bucket": "/var/jfs/",
"BlockSize": 4096,
"Compression": "none",
"EncryptAlgo": "aes256gcm-rsa",
"TrashDays": 1,
"MetaVersion": 1,
"MinClientVersion": "1.1.0-A",
"DirStats": true,
"EnableACL": false
} [[email protected]:621]
root@ubuntu:/# ~/juicefs-git/juicefs mount sqlite3://fstest.db /mnt/fstest --enable-xattr
2026/09/03 07:52:12.922152 juicefs[1486] <INFO>: Meta address: sqlite3://fstest.db [[email protected]:655]
2026/09/03 07:52:12.924108 juicefs[1486] <INFO>: Data use file:///var/jfs/fstest/ [[email protected]:619]
2026/09/03 07:52:12.955627 juicefs[1495] <INFO>: Meta address: sqlite3://fstest.db [[email protected]:655]
2026/09/03 07:52:12.957249 juicefs[1495] <INFO>: Data use file:///var/jfs/fstest/ [[email protected]:619]
2026/09/03 07:52:12.957289 juicefs[1495] <INFO>: JuiceFS version 1.5.0-dev+2026-09-03.f2f31b6f [[email protected]:662]
2026/09/03 07:52:12.957931 juicefs[1495] <INFO>: Disk cache (/var/jfsCache/351aef67-786f-431e-82f3-28da539acb17/): used ratio - [space 80.7%, inode 17.5%] [newDiskCache@disk_cache.go:145]
2026/09/03 07:52:12.958008 juicefs[1495] <INFO>: Adjusted cache capacity based on freeratio: from 107374182400 to 13886465680 bytes [setLimitByFreeRatio@disk_cache.go:168]
2026/09/03 07:52:12.958081 juicefs[1495] <INFO>: Adjusted max items based on freeratio: from 0 to 1693439 items [setLimitByFreeRatio@disk_cache.go:182]
2026/09/03 07:52:12.960283 juicefs[1495] <INFO>: Create session 1 OK with version: 1.5.0-dev+2026-09-03.f2f31b6f [[email protected]:805]
2026/09/03 07:52:12.961027 juicefs[1495] <INFO>: Prometheus metrics listening on "127.0.0.1:9567" [[email protected]:137]
2026/09/03 07:52:12.961624 juicefs[1495] <INFO>: Mounting volume fstest at "/mnt/fstest" ... [mountMain@mount_unix.go:1167]
2026-09-03 07:52:13.028840 I | Unimplemented opcode POLL
2026/09/03 07:52:13.029469 juicefs[1486] <INFO>: watching "/mnt/fstest", pid 1495 [watchdog@mount_unix.go:237]
2026/09/03 07:52:13.426108 juicefs[1486] <INFO>: OK, fstest is ready at "/mnt/fstest" [checkMountpoint@mount_unix.go:327]
2026/09/03 07:52:57.157083 juicefs[1495] <ERROR>: error: UNIQUE constraint failed: jfs_edge.parent, jfs_edge.name
goroutine 368 [running]:
runtime/debug.Stack()
/usr/lib/go-1.26/src/runtime/debug/stack.go:26 +0x5e
github.com/juicedata/juicefs/pkg/meta.errno({0x50a4f00, 0x3eb4c02bd770})
/root/juicefs-git/pkg/meta/utils.go:157 +0x16e
github.com/juicedata/juicefs/pkg/meta.(*dbMeta).doRename(0x3eb4bf766ac0, {0x512b240, 0x3eb4bf9a9040}, 0x1, {0x3eb4c01d8b14, 0x5}, 0x1, {0x3eb4c01d8b1c, 0x4}, 0x0, ...)
/root/juicefs-git/pkg/meta/sql.go:2663 +0x448
github.com/juicedata/juicefs/pkg/meta.(*baseMeta).Rename(0x3eb4bf369408, {0x512b240, 0x3eb4bf9a9040}, 0x1, {0x3eb4c01d8b14, 0x5}, 0x1, {0x3eb4c01d8b1c, 0x4}, 0x0, ...)
/root/juicefs-git/pkg/meta/base.go:1965 +0x90d
github.com/juicedata/juicefs/pkg/vfs.(*VFS).Rename(0x3eb4c02c1360, {0x512de60, 0x3eb4bf9a9040}, 0x1, {0x3eb4c01d8b14, 0x5}, 0x1, {0x3eb4c01d8b1c, 0x4}, 0x0)
/root/juicefs-git/pkg/vfs/vfs.go:374 +0x2fc
github.com/juicedata/juicefs/pkg/fuse.(*fileSystem).Rename(0x3eb4c056c0a0, 0x4a639d?, 0x3eb4bf7c86c0, {0x3eb4c01d8b14, 0x5}, {0x3eb4c01d8b1c, 0x4})
/root/juicefs-git/pkg/fuse/fuse.go:165 +0xd1
github.com/hanwen/go-fuse/v2/fuse.doRename(0x3eb4c02f2f00, 0x3eb4bf71a488)
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/opcode.go:487 +0xf4
github.com/hanwen/go-fuse/v2/fuse.init.1.func1(0x1a00000068?, 0x2?)
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/opcode.go:810 +0x43
github.com/hanwen/go-fuse/v2/fuse.(*Server).handleRequest(0x3eb4c02f2f00, 0x3eb4bf71a488)
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/server.go:821 +0x2f1
github.com/hanwen/go-fuse/v2/fuse.(*Server).loop(0x3eb4c02f2f00, 0x1)
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/server.go:794 +0x110
created by github.com/hanwen/go-fuse/v2/fuse.(*Server).readRequest in goroutine 1
/root/go/pkg/mod/github.com/juicedata/go-fuse/[email protected]/fuse/server.go:451 +0x668 [[email protected]:157]Environment:
- JuiceFS version (use
juicefs --version) or Hadoop Java SDK version:1.4.1+2026-07-30.0b90c7d&1.5.0-dev+2026-09-03.f2f31b6f - Cloud provider or hardware configuration running JuiceFS:
None - OS (e.g
cat /etc/os-release):Ubuntu 26.04.1 LTS - Kernel (e.g.
uname -a):Linux ubuntu 7.0.0-30-generic #30-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 31 18:22:54 UTC 2026 x86_64 GNU/Linux - Object storage (cloud provider and region, or self maintained):
Self - Metadata engine info (version, cloud provider managed or self maintained):
SQLite - Network connectivity (JuiceFS to metadata engine, JuiceFS to object storage):
None - Others:
None
Source: juicedata/juicefs