datawhalechina/hello-agents · error · FileWriteError

无法保存学习计划:{e}

Error message

无法保存学习计划:{e}

What it means

FileWriteError raised by FileManager.save_plan when writing the learning plan markdown to BASE_DIR/<domain>/plan.md fails. The original exception (permission denied, missing parent directory, disk full, path is a directory) is interpolated into the message. Note the parent directory is never created by this method, so a domain directory that does not yet exist is the most common cause.

Source

Thrown at Co-creation-projects/Yixiang-Wu-LearningAgent/core/file_manager.py:60

            "# 知识总结\n\n> 暂无知识笔记\n", encoding="utf-8"
        )
        (domain_path / "sessions" / "session_summary.md").write_text(
            "# 学习历程\n\n> 暂无学习记录\n", encoding="utf-8"
        )

    def save_plan(self, domain: str, plan_content: str) -> None:
        """
        保存学习计划

        Args:
            domain: 领域名称
            plan_content: 计划内容(markdown格式)
        """
        plan_path = self.BASE_DIR / domain / "plan.md"
        try:
            plan_path.write_text(plan_content, encoding="utf-8")
        except Exception as e:
            raise FileWriteError(f"无法保存学习计划:{e}")

    def save_knowledge(self, domain: str, filename: str, content: str) -> None:
        """
        保存知识笔记

        Args:
            domain: 领域名称
            filename: 文件名
            content: 文件内容
        """
        knowledge_path = self.BASE_DIR / domain / "knowledge" / filename
        try:
            knowledge_path.write_text(content, encoding="utf-8")
        except Exception as e:
            raise FileWriteError(f"无法保存知识笔记:{e}")

    def save_session(self, domain: str, session_content: str) -> Path:
        """

View on GitHub (pinned to 606a07d341)

Solutions

  1. mkdir the parent before writing: plan_path.parent.mkdir(parents=True, exist_ok=True) inside save_plan
  2. Sanitize the domain string (strip path separators and whitespace) before building the path
  3. Check filesystem permissions/ownership of BASE_DIR and the mounted volume in deployment
  4. Free up disk space or enlarge the volume if ENOSPC
  5. Include type(e).__name__ and the path in the message so future failures are diagnosable

Example fix

# before
plan_path = self.BASE_DIR / domain / "plan.md"
try:
    plan_path.write_text(plan_content, encoding="utf-8")
except Exception as e:
    raise FileWriteError(f"无法保存学习计划:{e}")

# after
plan_path = self.BASE_DIR / domain / "plan.md"
try:
    plan_path.parent.mkdir(parents=True, exist_ok=True)
    plan_path.write_text(plan_content, encoding="utf-8")
except OSError as e:
    raise FileWriteError(f"无法保存学习计划 {plan_path}: {type(e).__name__}: {e}") from e
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def can_write_plan(base_dir: Path, domain: str) -> bool:
    d = base_dir / domain
    if d.exists() and not d.is_dir():
        return False
    if d.exists():
        return os.access(d, os.W_OK)
    return os.access(base_dir, os.W_OK)

Try / catch

try:
    fm.save_plan(domain, content)
except FileWriteError as e:
    logger.error("save_plan failed for %s: %s", domain, e)
    # surface to user; do not retry without fixing FS

Prevention

When it happens

Trigger: Calling save_plan(domain, content) when BASE_DIR/<domain> does not exist (write_text does not create parent dirs); running the agent in a read-only container or with insufficient file permissions; BASE_DIR pointing to a path where <domain> collides with an existing file; disk-full or ENOSPC while writing; passing a domain containing path separators or invalid filename characters (e.g. '/', '\0') so the OS rejects the path.

Common situations: First run of a new domain before any directory scaffold was created; deploying to Docker where BASE_DIR is a mounted volume with root ownership; CI runners with read-only workspace; domain string taken from LLM output containing '/' or newline characters.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/0e3ea1d2446ed2b2. Report an issue: GitHub.