CoplayDev/unity-mcp · error · RuntimeError
{path}: expected to remove exactly 1 line '{line}', removed
Error message
{path}: expected to remove exactly 1 line '{line}', removed {removed} What it means
Raised by remove_line_exact() when the target line content is not found exactly once in the file. The function strips each line and compares it to the literal passed in; it aborts if the count is 0 (line absent or reformatted) or >1 (duplicate lines). This is a build-time guard ensuring the Asset Store release script's source-edit assumptions still hold against the current source tree.
Source
Thrown at tools/prepare_unity_asset_store_release.py:58
f"{path}: expected 1 replacement for pattern, got {n}")
if new != original:
write_text(path, new)
def remove_line_exact(path: Path, line: str) -> None:
original = read_text(path)
lines = original.splitlines(keepends=True)
removed = 0
kept: list[str] = []
for l in lines:
if l.strip() == line:
removed += 1
continue
kept.append(l)
if removed != 1:
raise RuntimeError(
f"{path}: expected to remove exactly 1 line '{line}', removed {removed}")
write_text(path, "".join(kept))
def backup_dir(src: Path, backup_root: Path) -> Path:
ts = dt.datetime.now().strftime("%Y%m%d-%H%M%S")
backup_path = backup_root / f"{src.name}.backup.{ts}"
shutil.copytree(src, backup_path)
return backup_path
def main() -> int:
parser = argparse.ArgumentParser(
description="Prepare MCPForUnity for Asset Store upload.")
parser.add_argument(
"--repo-root",
default=str(REPO_ROOT_DEFAULT),View on GitHub (pinned to c21bf496bc)
Solutions
- Open SetupWindowService.cs and grep for 'InitializeOnLoad' to see the current form of the attribute line.
- If the attribute sits on the same line as other tokens, update the literal passed to remove_line_exact (or switch to a regex-based removal) so the stripped comparison matches.
- If the attribute was already removed (removed=0), the edit is a no-op — skip the call or make it idempotent by treating removed==0 as success.
- If removed>1, disambiguate which occurrence to remove by adding surrounding context to the match logic.
Example fix
// before
remove_line_exact(setup_service, "[InitializeOnLoad]")
// after — idempotent: tolerate already-removed attribute
def remove_line_optional(path: Path, line: str) -> None:
original = read_text(path)
lines = original.splitlines(keepends=True)
kept = [l for l in lines if l.strip() != line]
if len(kept) != len(lines):
write_text(path, "".join(kept)) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def can_remove_line(path: Path, line: str) -> bool:
if not path.is_file():
return False
matches = [l for l in path.read_text(encoding="utf-8").splitlines() if l.strip() == line]
return len(matches) == 1
# Before calling remove_line_exact:
if not can_remove_line(setup_service, "[InitializeOnLoad]"):
print(f"Skip: line not found exactly once in {setup_service}") Try / catch
try:
remove_line_exact(setup_service, "[InitializeOnLoad]")
except RuntimeError as e:
print(f"Warning: skipping attribute removal — {e}")
# decide whether to abort or continue; the edit may already be applied Prevention
- Run the release script with --dry-run first to validate path assumptions before source edits.
- Keep the line literals in the script in sync with the source files via a pre-flight grep check.
- Treat removed==0 as idempotent success if the script may be re-run.
When it happens
Trigger: Called as remove_line_exact(setup_service, "[InitializeOnLoad]"). Fires when SetupWindowService.cs no longer contains a standalone line whose stripped value equals exactly "[InitializeOnLoad]". Occurs if the attribute was already removed in a prior run, moved onto the same line as a class/method declaration (so strip() yields a longer string), wrapped in a region, or if the attribute now appears on multiple lines.
Common situations: The source file evolved after the release script was written — e.g. the [InitializeOnLoad] attribute was inlined, commented out, or merged with a comment. Also fires on a second accidental run if the first already removed the line (removed=0).
Related errors
- Expected file not found: {f}
- --remote-url must be a non-empty URL
- Source MCPForUnity folder not found: {source_mcp}
- Assets folder not found: {assets_dir}
- Color array must have 3 or 4 elements.
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/d8f494435d25240f.
Report an issue: GitHub.