HKUDS/Vibe-Trading · error · ValueError

invalid preset name: {name!r}

Error message

invalid preset name: {name!r}

What it means

_validate_preset_name in swarm/presets.py sanitizes the preset name used to build filesystem paths. It raises ValueError for empty names, '.'/'..', or any name containing '/' or '\\' — a path-traversal guard. Called by resolve_preset_path.

Source

Thrown at agent/src/swarm/presets.py:62

        return str(path)


def _validate_preset_name(name: str) -> str:
    """Reject names that are empty or could escape a presets directory.

    Preset names map directly to ``<dir>/<name>.yaml``; a name carrying a
    path separator or ``..`` would resolve outside the directory. The bundled
    path had the same latent exposure — validating here covers both.

    Returns:
        The stripped name.

    Raises:
        ValueError: Empty name, path separators, or parent references.
    """
    cleaned = (name or "").strip()
    if not cleaned or cleaned in {".", ".."} or "/" in cleaned or "\\" in cleaned:
        raise ValueError(f"invalid preset name: {name!r}")
    return cleaned


def _preset_search_dirs() -> tuple[Path, ...]:
    """Directories searched for presets, highest priority first."""
    return (USER_PRESETS_DIR, PRESETS_DIR)


def resolve_preset_path(name: str) -> Path | None:
    """Return the YAML path for *name* (user dir first), or ``None``."""
    cleaned = _validate_preset_name(name)
    for directory in _preset_search_dirs():
        path = directory / f"{cleaned}.yaml"
        if path.is_file():
            return path
    return None

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use a bare preset name like 'default' or 'research-full' (flat name, no directories)
  2. Validate/normalize external input before calling load_preset
  3. If you need hierarchy, encode it in the filename, e.g. 'research-full.yaml'

Example fix

# before
load_preset('user/configs/default')
# after
load_preset('default')
Defensive patterns

Strategy: type-guard

Validate before calling

def safe_preset_name(name: str) -> bool:
    n = (name or '').strip()
    return bool(n) and n not in {'.','..'} and '/' not in n and '\\' not in n

Type guard

def is_bare_preset_name(name) -> bool:
    return isinstance(name, str) and bool(name.strip()) and name.strip() not in {'.','..'} and '/' not in name and '\\' not in name

Try / catch

try:
    load_preset(name)
except ValueError as e:
    if 'invalid preset name' in str(e): return 400 to the caller / strip separators and retry
    else: raise

Prevention

When it happens

Trigger: Calling load_preset/resolve_preset_path with '../../etc/passwd', 'foo/bar', 'C:\\presets\\x', an empty string, or None.

Common situations: Passing user-supplied preset names straight from CLI/web input; building nested preset paths assuming subdirectories are supported (they are not — presets are flat *.yaml files).

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/77df6310ef7c75f6. Report an issue: GitHub.