oraios/serena · error · ValueError

Memory name cannot contain '..' segments. Got: {name}

Error message

Memory name cannot contain '..' segments. Got: {name}

What it means

get_memory_file_path explicitly rejects memory names containing '..' segments with a ValueError before resolving the path. This is a path-traversal guard: '..' would let a memory name address files outside the .serena/memories sandbox.

Source

Thrown at src/serena/memories/memory_manager.py:178

        resolution): directory symlinks placed inside the memories folder are a supported way to
        share memories (e.g. a monorepo symlinking each submodule's memory dir), and those must
        keep resolving to their targets at I/O time.
        """
        filename = f"{parts[-1]}.md"
        subdir = base_dir if len(parts) == 1 else base_dir.joinpath(*parts[:-1])
        candidate = subdir / filename
        base_norm = Path(os.path.normpath(base_dir))
        if not Path(os.path.normpath(candidate)).is_relative_to(base_norm):
            raise ValueError(f"Memory name resolves outside the memories directory. Got: {'/'.join(parts)}")
        subdir.mkdir(parents=True, exist_ok=True)
        return candidate

    def get_memory_file_path(self, name: str) -> Path:
        name = self._sanitize_name(name)
        parts = name.split("/")

        if ".." in parts:
            raise ValueError(f"Memory name cannot contain '..' segments. Got: {name}")

        # Reject absolute names and empty path segments: pathlib discards the base directory when
        # joined with an absolute path (e.g. "/etc/cron.d/backdoor" would reset to "/etc/cron.d"),
        # letting a memory name escape the sandbox. A leading "/" produces an empty first segment.
        if os.path.isabs(name) or "" in parts:
            raise ValueError(f"Memory name cannot be absolute or contain empty path segments. Got: {name}")

        if self._is_global(name):
            if name == self.GLOBAL_TOPIC:
                raise ValueError(
                    f'Bare "{self.GLOBAL_TOPIC}" is not a valid memory name. Use "{self.GLOBAL_TOPIC}/<name>" to address a global memory.'
                )
            # Strip "global/" prefix and resolve against global dir
            sub_name = name[len(self.GLOBAL_TOPIC) + 1 :]
            return self._resolve_memory_path(self._global_memory_dir, sub_name.split("/"))

        # Project-local memory
        assert self._project_memory_dir is not None, "Project dir was not passed at initialization"

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Remove '..' segments and address the memory by its name within the memories directory.
  2. If the target file lives outside memories, use the read_file tool on its absolute path instead.
  3. Validate or normalize names from untrusted sources before passing them to memory APIs (reject any name containing '..').
  4. Note names are sanitized first ('mem:' prefix, '.md' suffix, OS separators removed) — after sanitization '..' still means a literal dot-dot segment and is invalid.

Example fix

// before
manager.load_memory("../secrets/keys")
// after
manager.load_memory("secrets/keys")  # stays inside .serena/memories
Defensive patterns

Strategy: validation

Validate before calling

if ".." in name.split("/"):
    raise ValueError(f"memory name must not contain '..': {name!r}")

Type guard

def has_no_dotdot(name: str) -> bool:
    return ".." not in name.split("/")

Try / catch

try:
    content = manager.load_memory(name)
except ValueError as e:
    if "'..'" in str(e):
        log.warning("traversal blocked for %r; use read_file for external files", name)
    else:
        raise

Prevention

When it happens

Trigger: Calling load_memory, save_memory, delete_memory, move_memory, edit_memory, or get_memory_file_path with a name like "../config" or "topic/../../secrets" (the '..' check precedes the absolute/empty-segment check).

Common situations: LLM agents hallucinating relative-style memory names; users trying to read files outside the project memories dir through the memory tool; scripting that interpolates user input into memory names.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/381047574a2b111f. Report an issue: GitHub.