abi/screenshot-to-code · error · InvalidSetNameError

Not a set image: {filename!r}

Error message

Not a set image: {filename!r}

What it means

resolve_set_image_path raises InvalidSetNameError("Not a set image") when the filename (after basename normalization) does not end in .png. The function only serves PNG files from a set's inputs directory, so JPG/WEBP/JSON or extension-less filenames are rejected before any filesystem access. basename() is applied first, so path components never reach this check — only the final extension matters.

Source

Thrown at backend/evals/sets.py:297

            continue
        set_dir = os.path.join(sets_dir, entry)
        if not (
            os.path.isdir(os.path.join(set_dir, "inputs"))
            or os.path.isfile(os.path.join(set_dir, "briefs.json"))
        ):
            continue
        infos.append(get_set(entry))
    return infos


def resolve_set_image_path(set_name: str, filename: str) -> str:
    """Absolute path of a set image; raises on traversal or missing file."""
    inputs_dir = get_set_inputs_dir(set_name)
    if not os.path.isdir(inputs_dir):
        raise EvalSetNotFoundError(f"Eval set not found: {set_name}")
    safe_name = os.path.basename(filename)
    if not safe_name.lower().endswith(".png"):
        raise InvalidSetNameError(f"Not a set image: {filename!r}")
    path = os.path.realpath(os.path.join(inputs_dir, safe_name))
    if not path.startswith(os.path.realpath(inputs_dir) + os.sep):
        raise InvalidSetNameError(f"Invalid image path: {filename!r}")
    if not os.path.isfile(path):
        raise FileNotFoundError(path)
    return path

View on GitHub (pinned to d026163f58)

Solutions

  1. Convert non-PNG inputs to PNG before dropping them into inputs/ (only PNGs are supported).
  2. Fix the requested filename to end with .png (any casing).
  3. On the caller side, filter filenames with filename.lower().endswith('.png') before resolving.
Defensive patterns

Strategy: type-guard

Validate before calling

def is_png_filename(filename: str) -> bool:
    return os.path.basename(filename).lower().endswith(".png")

Type guard

def is_set_image_filename(filename: str) -> bool:
    """True when resolve_set_image_path will accept the filename."""
    return bool(filename) and os.path.basename(filename).lower().endswith(".png")

Try / catch

try:
    path = resolve_set_image_path(set_name, filename)
except InvalidSetNameError:
    abort(400, description="only .png set images are served")

Prevention

When it happens

Trigger: Calling resolve_set_image_path(name, "shot.jpg"), "manifest.json", "image" (no extension), or a URL like "/images/shot.png?raw" where the query string survives into the filename. Case is handled (.PNG passes), so only genuinely non-PNG suffixes trigger it.

Common situations: Frontend building image URLs from files that are not PNG; a set folder accidentally containing .jpg screenshots the user expects to serve; typos or missing extensions in hardcoded URLs.

Related errors


AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14). Data as JSON: /api/errors/d15f33ea5bad4cab. Report an issue: GitHub.