FoundationAgents/MetaGPT · error · FileNotFoundError

{image_path_or_pil} not exists

Error message

{image_path_or_pil} not exists

What it means

encode_image in metagpt/utils/common.py base64-encodes either a PIL.Image (in memory) or an image file from disk. For the file path branch it converts str to Path and checks .exists(); a nonexistent path raises FileNotFoundError before the file is opened.

Source

Thrown at metagpt/utils/common.py:853

    if not skills_dir:
        skills_dir = Path(__file__).parent.absolute()
    if skill_names is None:
        skill_names = [skill[:-3] for skill in os.listdir(f"{skills_dir}") if skill.endswith(".js")]
    skills = [skills_dir.joinpath(f"{skill_name}.js").read_text() for skill_name in skill_names]
    return skills


def encode_image(image_path_or_pil: Union[Path, Image, str], encoding: str = "utf-8") -> str:
    """encode image from file or PIL.Image into base64"""
    if isinstance(image_path_or_pil, Image.Image):
        buffer = BytesIO()
        image_path_or_pil.save(buffer, format="JPEG")
        bytes_data = buffer.getvalue()
    else:
        if isinstance(image_path_or_pil, str):
            image_path_or_pil = Path(image_path_or_pil)
        if not image_path_or_pil.exists():
            raise FileNotFoundError(f"{image_path_or_pil} not exists")
        with open(str(image_path_or_pil), "rb") as image_file:
            bytes_data = image_file.read()
    return base64.b64encode(bytes_data).decode(encoding)


def decode_image(img_url_or_b64: str) -> Image:
    """decode image from url or base64 into PIL.Image"""
    if img_url_or_b64.startswith("http"):
        # image http(s) url
        resp = requests.get(img_url_or_b64)
        img = Image.open(BytesIO(resp.content))
    else:
        # image b64_json
        b64_data = re.sub("^data:image/.+;base64,", "", img_url_or_b64)
        img_data = BytesIO(base64.b64decode(b64_data))
        img = Image.open(img_data)
    return img

View on GitHub (pinned to 11cdf466d0)

Solutions

  1. Print/verify the resolved path: Path(image_path_or_pil).resolve().
  2. Ensure the screenshot/creation step completed (await it) before encoding.
  3. Anchor relative paths to an explicit base directory instead of cwd.
  4. If you already hold a PIL.Image, pass the Image object directly to skip filesystem lookup.

Example fix

# before
b64 = encode_image('shot.png')  # relative to unpredictable cwd

# after
from pathlib import Path
p = workspace_dir / 'shot.png'
assert p.exists()
b64 = encode_image(str(p))
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def image_encodable(p) -> bool:
    return Path(p).is_file()

Try / catch

try:
    b64 = encode_image(path)
except FileNotFoundError:
    # await/regenerate the screenshot, verify path, then retry

Prevention

When it happens

Trigger: encode_image('/tmp/shot.png') when the screenshot step failed or wrote elsewhere; relative path resolved from a different cwd; typo or wrong extension; the file is created asynchronously and isn't there yet when encode is called.

Common situations: Browser screenshot saved into a per-run workspace directory while encoding uses a bare relative name; race where the screenshot future hasn't completed; path built by joining components where one is None (producing 'None' in the path).

Related errors


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