{"record":{"id":"2be949d3661f6d47","repo":"ipfs/kubo","slug":"cannot-write-to-s-incorrect-permissions","errorCode":null,"errorMessage":"cannot write to %s, incorrect permissions","messagePattern":"cannot write to (.+?), incorrect permissions","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/ipfs/kubo/init.go","lineNumber":200,"sourceCode":"\t\ttestfile := filepath.Join(dir, \"test\")\n\t\tfi, err := os.Create(testfile)\n\t\tif err != nil {\n\t\t\tif os.IsPermission(err) {\n\t\t\t\treturn fmt.Errorf(\"%s is not writeable by the current user\", dir)\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"unexpected error while checking writeablility of repo root: %s\", err)\n\t\t}\n\t\tfi.Close()\n\t\treturn os.Remove(testfile)\n\t}\n\n\tif os.IsNotExist(err) {\n\t\t// dir doesn't exist, check that we can create it\n\t\treturn os.Mkdir(dir, 0o775)\n\t}\n\n\tif os.IsPermission(err) {\n\t\treturn fmt.Errorf(\"cannot write to %s, incorrect permissions\", err)\n\t}\n\n\treturn err\n}\n\nfunc addDefaultAssets(out io.Writer, repoRoot string) error {\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tr, err := fsrepo.Open(repoRoot)\n\tif err != nil { // NB: repo is owned by the node\n\t\treturn err\n\t}\n\n\tnd, err := core.NewNode(ctx, &core.BuildCfg{Repo: r})\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/cmd/ipfs/kubo/init.go#L182-L218","documentation":"Thrown by checkWritable when stat-ing the repo dir itself fails with a permission error (the dir's parent is inaccessible to the current user). Kubo tells you the directory cannot be written due to permissions. Note a formatting bug in the source: the message interpolates the error value `err` where the directory path was intended, so the %s shows the underlying error text rather than the path.","triggerScenarios":"IPFS_PATH (or target dir) exists per the caller but os.Stat returns a permission error — typically a non-executable (no x bit) ancestor directory blocking traversal, e.g. ~/private/parent with mode 0600, so stat of the dir itself gets EACCES.","commonSituations":"IPFS_PATH placed inside another user's home or a locked-down directory whose parents deny +x; a hardened permissions setup accidentally removing execute bits from a path component; container setups with restrictive volume modes.","solutions":["Add execute (traverse) permission on every ancestor of the path: `chmod +x <parent-dirs>` along IPFS_PATH.","Move IPFS_PATH to a location with traversable parents, e.g. `export IPFS_PATH=$(mktemp -d)`.","Ignore the misleading text after 'cannot write to' (it contains the OS error, not the path): the path is whatever IPFS_PATH or the init argument was; re-check it with `ls -ld`."],"exampleFix":"// before\nchmod 600 /home/user/data   # blocks traversal, init fails\n// after\nchmod 755 /home/user/data   # or move IPFS_PATH elsewhere","handlingStrategy":"validation","validationCode":"dir := os.Getenv(\"IPFS_PATH\")\nif dir == \"\" {\n\tdir = \"~/.ipfs\"\n}\nif _, err := os.Stat(dir); os.IsPermission(err) {\n\tlog.Fatalf(\"cannot traverse to %s: %v — check +x on all ancestors\", dir, err)\n}\nfor p := filepath.Dir(dir); p != \"/\"; p = filepath.Dir(p) {\n\tif fi, err := os.Stat(p); err == nil && fi.Mode().Perm()&0o100 == 0 {\n\t\tlog.Fatalf(\"ancestor %s blocks traversal (missing x bit)\", p)\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep execute bits (traversal) on every ancestor of IPFS_PATH","Do not place IPFS_PATH inside directories owned by other users","Remember this error's message prints the OS error, not the path — always check IPFS_PATH itself"],"tags":["filesystem","permissions","init"],"backgroundTag":"directory-not-writable","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}