xpzouying/xiaohongshu-mcp · error

create cookies dir failed

Error message

create cookies dir failed

What it means

The write helper fails when os.MkdirAll cannot create the parent directory of the cookie file path (cookies/cookies.go:111). This runs before writing the file, guaranteeing nested save paths exist. Failure means the OS refused directory creation: permission denied, a non-directory file occupies the path, or the path is invalid.

Source

Thrown at cookies/cookies.go:111

// write 以 v2 格式落盘。cookies 用 RawMessage 原样嵌入,不经过结构体往返。
func (c *localCookie) write(cks []byte, seed int) error {
	if len(cks) == 0 {
		cks = []byte("[]")
	}

	data, err := json.MarshalIndent(sessionFile{
		Version: 2,
		Seed:    seed,
		SavedAt: time.Now().Format(time.RFC3339),
		Cookies: json.RawMessage(cks),
	}, "", "  ")
	if err != nil {
		return errors.Wrap(err, "marshal session file failed")
	}

	if dir := filepath.Dir(c.path); dir != "" && dir != "." {
		if err := os.MkdirAll(dir, 0755); err != nil {
			return errors.Wrap(err, "create cookies dir failed")
		}
	}

	return os.WriteFile(c.path, data, 0644)
}

// DeleteCookies 删除 cookies 文件。
func (c *localCookie) DeleteCookies() error {
	if _, err := os.Stat(c.path); os.IsNotExist(err) {
		// 文件不存在,返回 nil(认为已经删除)
		return nil
	}
	return os.Remove(c.path)
}

// GetCookiesFilePath 获取 cookies 文件路径。
// 为了向后兼容,如果旧路径 /tmp/cookies.json 存在,则继续使用;
// 否则使用当前目录下的 cookies.json

View on GitHub (pinned to 332d196854)

Solutions

  1. Inspect the wrapped os error: EACCES → fix directory permissions or pick a writable path; ENOTDIR → remove/replace the file occupying a path segment.
  2. Set COOKIES_PATH (or the NewLoadCookie path) to a directory the process can write, e.g. $HOME or the working directory.
  3. In containers, mount the target volume as read-write.
  4. Pre-create the directory manually and verify with a touch test if unsure.

Example fix

// before
os.Setenv("COOKIES_PATH", "/root/secure/cookies.json")
// after
os.Setenv("COOKIES_PATH", filepath.Join(os.Getenv("HOME"), ".xhs", "cookies.json"))
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0755); err != nil {
    return fmt.Errorf("cannot prepare cookie dir %s: %w", dir, err)
}

Try / catch

err := store.SaveCookies(cks)
if err != nil && strings.Contains(err.Error(), "create cookies dir failed") {
    return fmt.Errorf("fix COOKIES_PATH permissions: %w", err)
}

Prevention

When it happens

Trigger: Calling SaveCookies or SaveSeed with a cookie path whose parent directory can't be created — e.g. COOKIES_PATH=/root/cookies/cookies.json as a non-root user, a path segment being an existing regular file, or read-only filesystem in containers.

Common situations: Pointing COOKIES_PATH into a system directory without write access; Docker volume mounted read-only; a file named like a directory already exists on the path; Windows path with illegal characters.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05). Data as JSON: /api/errors/d476269ef97caf06. Report an issue: GitHub.