@cryptotaxi247 / kubo / commits / f84fb2849

fix(fuse): ipns error handling and friendly errors (#10807)

* fix(fusei/ux): check if paths exist, print err * fix(fuse): ipns 'could not resolve' error type changed when code got extracted to boxo, but it was not caught because of FUSE tests do not cover IPNS in online mode Closes #8095 Closes #2167 Closes #3013 * docs: clarify opt-in

Marcin Rataj committed May 15, 2025 at 23:43 UTC f84fb2849bb64df667dd65c1912a0e691001ea06
3 files changed +35 -2
cmd/ipfs/kubo/daemon.go
+29
@@ -1065,16 +1065,25 @@ func mountFuse(req *cmds.Request, cctx *oldcmds.Context) error {
1065 if !found {
1066 fsdir = cfg.Mounts.IPFS
1067 }
1068 + if err := checkFusePath("Mounts.IPFS", fsdir); err != nil {
1069 + return err
1070 + }
1071
1072 nsdir, found := req.Options[ipnsMountKwd].(string)
1073 if !found {
1074 nsdir = cfg.Mounts.IPNS
1075 }
1076 + if err := checkFusePath("Mounts.IPNS", nsdir); err != nil {
1077 + return err
1078 + }
1079
1080 mfsdir, found := req.Options[mfsMountKwd].(string)
1081 if !found {
1082 mfsdir = cfg.Mounts.MFS
1083 }
1084 + if err := checkFusePath("Mounts.MFS", mfsdir); err != nil {
1085 + return err
1086 + }
1087
1088 node, err := cctx.ConstructNode()
1089 if err != nil {
@@ -1091,6 +1100,26 @@ func mountFuse(req *cmds.Request, cctx *oldcmds.Context) error {
1100 return nil
1101 }
1102
1103 +func checkFusePath(name, path string) error {
1104 + if path == "" {
1105 + return fmt.Errorf("%s path cannot be empty", name)
1106 + }
1107 +
1108 + fileInfo, err := os.Stat(path)
1109 + if err != nil {
1110 + if os.IsNotExist(err) {
1111 + return fmt.Errorf("%s path (%q) does not exist: %w", name, path, err)
1112 + }
1113 + return fmt.Errorf("error while inspecting %s path (%q): %w", name, path, err)
1114 + }
1115 +
1116 + if !fileInfo.IsDir() {
1117 + return fmt.Errorf("%s path (%q) is not a directory", name, path)
1118 + }
1119 +
1120 + return nil
1121 +}
1122 +
1123 func maybeRunGC(req *cmds.Request, node *core.IpfsNode) (<-chan error, error) {
1124 enableGC, _ := req.Options[enableGCKwd].(bool)
1125 if !enableGC {
docs/config.md
+4 -1
@@ -1373,7 +1373,10 @@ Default: `cache`
1373 ## `Mounts`
1374
1375 > [!CAUTION]
1376 -> **EXPERIMENTAL:** read about current limitations at [fuse.md](./fuse.md).
1376 +> **EXPERIMENTAL:**
1377 +> This feature is disabled by default, requires an explicit opt-in with `ipfs mount` or `ipfs daemon --mount`.
1378 +>
1379 +> Read about current limitations at [fuse.md](./fuse.md).
1380
1381 FUSE mount point configuration options.
1382
fuse/ipns/ipns_unix.go
+2 -1
@@ -16,6 +16,7 @@ import (
16
17 dag "github.com/ipfs/boxo/ipld/merkledag"
18 ft "github.com/ipfs/boxo/ipld/unixfs"
19 + "github.com/ipfs/boxo/namesys"
20 "github.com/ipfs/boxo/path"
21
22 fuse "bazil.org/fuse"
@@ -95,7 +96,7 @@ func loadRoot(ctx context.Context, ipfs iface.CoreAPI, key iface.Key) (*mfs.Root
96 node, err := ipfs.ResolveNode(ctx, key.Path())
97 switch err {
98 case nil:
98 - case iface.ErrResolveFailed:
99 + case namesys.ErrResolveFailed:
100 node = ft.EmptyDirNode()
101 default:
102 log.Errorf("looking up %s: %s", key.Path(), err)