{"record":{"id":"7fb67222499b1873","repo":"syncthing/syncthing","slug":"reading-folder-token-w","errorCode":null,"errorMessage":"reading folder token: %w","messagePattern":"reading folder token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/syncthing/decrypt/decrypt.go","lineNumber":123,"sourceCode":"// continue processing.\nfunc (c *CLI) withContinue(err error) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\tif c.Continue {\n\t\tlog.Println(\"Warning:\", err)\n\t\treturn nil\n\t}\n\treturn err\n}\n\n// getFolderID returns the folder ID found in the encrypted token, or an\n// error.\nfunc (c *CLI) getFolderID() (string, error) {\n\ttokenPath := filepath.Join(c.Path, c.TokenPath)\n\tbs, err := os.ReadFile(tokenPath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"reading folder token: %w\", err)\n\t}\n\n\tvar tok storedEncryptionToken\n\tif err := json.Unmarshal(bs, &tok); err != nil {\n\t\treturn \"\", fmt.Errorf(\"parsing folder token: %w\", err)\n\t}\n\n\treturn tok.FolderID, nil\n}\n\n// process handles the file named path in srcFs, decrypting it into dstFs\n// unless dstFs is nil.\nfunc (c *CLI) process(srcFs fs.Filesystem, dstFs fs.Filesystem, path string) error {\n\t// Which filemode bits to preserve\n\tconst retainBits = fs.ModePerm | fs.ModeSetgid | fs.ModeSetuid | fs.ModeSticky\n\n\tif c.Verbose {\n\t\tlog.Printf(\"Processing %q\", path)","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/syncthing/syncthing/blob/058bcd7334839663cf569501d3ac539034d45cb5/cmd/syncthing/decrypt/decrypt.go#L105-L141","documentation":"Raised inside getFolderID() (cmd/syncthing/decrypt/decrypt.go) when os.ReadFile fails on the encryption token file at filepath.Join(c.Path, c.TokenPath) — by default <Path>/.stfolder/encryption-token. The underlying error is wrapped, so the message includes the exact OS failure (no such file, permission denied, etc.). It propagates up as 'getting folder ID: reading folder token: ...'.","triggerScenarios":"`syncthing decrypt` without --folder-id where the token path doesn't exist (wrong --path depth, missing .stfolder), permission bits prevent reading the token, --token-path points at a custom location that doesn't exist, or the file was excluded during transfer/backup of the encrypted folder.","commonSituations":"rsync/rclone copies that skip hidden directories; running as a user without read access to .stfolder; passing an inner subfolder as --path; encrypted archive extracted without hidden files.","solutions":["Check the exact path in the error: confirm <Path>/.stfolder/encryption-token exists with ls -la","Fix --path to the encrypted folder root (where .stfolder sits)","Fix permissions (chmod a+r or run as owner) if the OS error is 'permission denied'","Bypass the token entirely with --folder-id if you know the ID"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-flight the token path exactly as the CLI computes it\ntokenPath := filepath.Join(cliPath, tokenPathRel) // default tokenPathRel = \".stfolder/encryption-token\"\nif fi, err := os.Stat(tokenPath); err != nil || fi.Size() == 0 {\n\treturn fmt.Errorf(\"token missing/empty at %s: pass --folder-id instead\", tokenPath)\n}","typeGuard":"func isTokenReadErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"reading folder token: \")\n}","tryCatchPattern":"// Inspect the wrapped *fs.PathError for the real cause\nvar pe *fs.PathError\nif errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrNotExist) {\n\t// wrong --path or .stfolder not copied\n} else if errors.Is(pe.Err, fs.ErrPermission) {\n\t// fix perms / run as owner\n}","preventionTips":["Run decrypt as a user with read access to the whole encrypted tree including hidden dirs","Verify the encrypted folder root with `ls -la <dir>/.stfolder/` before decrypting","Prefer explicit --folder-id so a missing token never blocks you"],"tags":["cli","decrypt","filesystem","folder-token"],"backgroundTag":null,"analyzedSha":"058bcd7334839663cf569501d3ac539034d45cb5","analyzedAt":"2026-08-15T07:53:43.174Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}