syncthing/syncthing · error

reading folder token: %w

Error message

reading folder token: %w

What it means

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: ...'.

Source

Thrown at cmd/syncthing/decrypt/decrypt.go:123

// continue processing.
func (c *CLI) withContinue(err error) error {
	if err == nil {
		return nil
	}
	if c.Continue {
		log.Println("Warning:", err)
		return nil
	}
	return err
}

// getFolderID returns the folder ID found in the encrypted token, or an
// error.
func (c *CLI) getFolderID() (string, error) {
	tokenPath := filepath.Join(c.Path, c.TokenPath)
	bs, err := os.ReadFile(tokenPath)
	if err != nil {
		return "", fmt.Errorf("reading folder token: %w", err)
	}

	var tok storedEncryptionToken
	if err := json.Unmarshal(bs, &tok); err != nil {
		return "", fmt.Errorf("parsing folder token: %w", err)
	}

	return tok.FolderID, nil
}

// process handles the file named path in srcFs, decrypting it into dstFs
// unless dstFs is nil.
func (c *CLI) process(srcFs fs.Filesystem, dstFs fs.Filesystem, path string) error {
	// Which filemode bits to preserve
	const retainBits = fs.ModePerm | fs.ModeSetgid | fs.ModeSetuid | fs.ModeSticky

	if c.Verbose {
		log.Printf("Processing %q", path)

View on GitHub (pinned to 058bcd7334)

Solutions

  1. Check the exact path in the error: confirm <Path>/.stfolder/encryption-token exists with ls -la
  2. Fix --path to the encrypted folder root (where .stfolder sits)
  3. Fix permissions (chmod a+r or run as owner) if the OS error is 'permission denied'
  4. Bypass the token entirely with --folder-id if you know the ID
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight the token path exactly as the CLI computes it
tokenPath := filepath.Join(cliPath, tokenPathRel) // default tokenPathRel = ".stfolder/encryption-token"
if fi, err := os.Stat(tokenPath); err != nil || fi.Size() == 0 {
	return fmt.Errorf("token missing/empty at %s: pass --folder-id instead", tokenPath)
}

Type guard

func isTokenReadErr(err error) bool {
	return err != nil && strings.Contains(err.Error(), "reading folder token: ")
}

Try / catch

// Inspect the wrapped *fs.PathError for the real cause
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrNotExist) {
	// wrong --path or .stfolder not copied
} else if errors.Is(pe.Err, fs.ErrPermission) {
	// fix perms / run as owner
}

Prevention

When it happens

Trigger: `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.

Common situations: 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.

Related errors


AI-assisted analysis of syncthing/syncthing@058bcd7334 (2026-08-15). Data as JSON: /api/errors/7fb67222499b1873. Report an issue: GitHub.