FoundationAgents/MetaGPT · error · ValueError

`to_replace` and `new_content` must be different.

Error message

`to_replace` and `new_content` must be different.

What it means

Raised by Editor._edit_file_by_replace at the top of the call when to_replace == new_content. A replace that changes nothing is treated as a caller error (likely a copy-paste mistake), and the tool refuses the no-op before touching the file.

Source

Thrown at metagpt/tools/libs/editor.py:876

        edit_file_by_replace(
            '/workspace/example.txt',
            to_replace='line 2\nline 3',
            new_content='',
        )

        Args:
            file_name: (str): The name of the file to edit.
            to_replace: (str): The content to search for and replace.
            new_content: (str): The new content to replace the old content with.
        NOTE:
            This tool is exclusive. If you use this tool, you cannot use any other commands in the current response.
            If you need to use it multiple times, wait for the next turn.
        """
        # FIXME: support replacing *all* occurrences

        if to_replace == new_content:
            raise ValueError("`to_replace` and `new_content` must be different.")

        # search for `to_replace` in the file
        # if found, replace it with `new_content`
        # if not found, perform a fuzzy search to find the closest match and replace it with `new_content`
        file_name = self._try_fix_path(file_name)
        with file_name.open("r") as file:
            file_content = file.read()

        if to_replace.strip() == "":
            if file_content.strip() == "":
                raise ValueError(f"The file '{file_name}' is empty. Please use the append method to add content.")
            raise ValueError("`to_replace` must not be empty.")

        if file_content.count(to_replace) > 1:
            raise ValueError(
                "`to_replace` appears more than once, please include enough lines to make code in `to_replace` unique."
            )
        start = file_content.find(to_replace)

View on GitHub (pinned to 11cdf466d0)

Solutions

  1. Make sure new_content actually differs from to_replace (diff the two strings before calling)
  2. If the source of new_content defaulted to the original, fix the upstream substitution
  3. Skip the call entirely when the strings are equal — it would be a no-op anyway

Example fix

// before
editor.edit_file_by_replace(path, to_replace=s, new_content=s)  # ValueError

// after
if new_content != to_replace:
    editor.edit_file_by_replace(path, to_replace=to_replace, new_content=new_content)
Defensive patterns

Strategy: validation

Validate before calling

if to_replace == new_content:
    raise ValueError('no-op replace; check that new_content was filled in')
editor.edit_file_by_replace(path, to_replace, new_content)

Type guard

def is_real_replace(old: str, new: str) -> bool:
    return old != new

Try / catch

try:
    editor.edit_file_by_replace(path, to_replace, new_content)
except ValueError as e:
    if 'must be different' in str(e):
        return 'no-op'  # treat as success or fix upstream substitution
    raise

Prevention

When it happens

Trigger: editor.edit_file_by_replace(path, to_replace=X, new_content=X); an LLM echoing the original snippet as the replacement; templating code that falls back to the original string when a substitution variable is empty.

Common situations: Agent pipelines where the 'new code' slot is populated from the same source as 'old code'; template default values collapsing to identity; debugging sessions where the intended change was never filled in.

Related errors


AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14). Data as JSON: /api/errors/807f27dd56f41af8. Report an issue: GitHub.