huggingface/open-r1 · error

No Piston endpoints provided. Please check your PISTON_ENDPO

Error message

No Piston endpoints provided. Please check your PISTON_ENDPOINTS environment variable.

What it means

The PistonClient constructor normalizes base_endpoint into a list; if the resulting list is empty, there is nothing to send requests to, so __init__ raises ValueError. This is a defensive check for an explicitly-provided-but-empty endpoint list.

Source

Thrown at src/open_r1/utils/competitive_programming/piston_client.py:68

    sed -i '/app.use(body_parser.urlencoded/c\    app.use(body_parser.urlencoded({ extended: true, limit: \"512mb\" }));' src/index.js
    sed -i '/app.use(body_parser.json/c\    app.use(body_parser.json({ limit: \"512mb\" }));' src/index.js

    # Start server in background
    node src```

    Piston docs for API usage: https://piston.readthedocs.io/en/latest/api-v2/
    """

    def __init__(
        self,
        base_endpoint: str | list[str] = "http://ip-10-53-80-65:3223/api/v2",
        session=None,
        max_requests_per_endpoint=1,
    ):
        self.max_requests_per_endpoint = max_requests_per_endpoint
        self.base_endpoints = [base_endpoint] if isinstance(base_endpoint, str) else base_endpoint
        if len(self.base_endpoints) == 0:
            raise ValueError("No Piston endpoints provided. Please check your PISTON_ENDPOINTS environment variable.")
        self.endpoint_ids = {endpoint: i for i, endpoint in enumerate(self.base_endpoints)}

        self._session = session
        self.endpoint_tokens = asyncio.Queue(maxsize=max_requests_per_endpoint * len(self.base_endpoints))

        for _ in range(max_requests_per_endpoint):
            for base_endpoint in self.base_endpoints:
                self.endpoint_tokens.put_nowait(base_endpoint)
        self._endpoint_failures = Counter()
        self._unhealthy_endpoints = set()
        self._endpoint_failures_lock = asyncio.Lock()

    @property
    def session(self):
        if self._session is None:
            self._session = aiohttp.ClientSession(
                timeout=aiohttp.ClientTimeout(sock_read=30),
                connector=aiohttp.TCPConnector(

View on GitHub (pinned to 1416fa0cf2)

Solutions

  1. Populate PISTON_ENDPOINTS with at least one reachable endpoint URL.
  2. If constructing PistonClient directly, pass a non-empty list or string of endpoints.
  3. Guard your config-loading code: strip whitespace and filter empty strings from the split list before instantiation.
  4. Check code paths that prune unhealthy endpoints so they don't hand an empty list to a new client.

Example fix

// before
endpoints = [e for e in os.getenv('PISTON_ENDPOINTS','').split(',') if e] or []
client = PistonClient(endpoints)  # ValueError
// after
assert endpoints, 'PISTON_ENDPOINTS must contain at least one endpoint'
client = PistonClient(endpoints)
Defensive patterns

Strategy: validation

Validate before calling

raw = os.getenv('PISTON_ENDPOINTS', '')
endpoints = [e.strip() for e in raw.split(',') if e.strip()] if raw != 'slurm' else get_slurm_piston_endpoints()
assert endpoints, 'PISTON_ENDPOINTS resolved to an empty endpoint list'

Type guard

def has_endpoints(x) -> bool:
    eps = [x] if isinstance(x, str) else (x or [])
    return len(eps) > 0 and all(isinstance(e, str) and e.strip() for e in eps)

Try / catch

try:
    client = PistonClient(base_endpoint=endpoints)
except ValueError as e:
    if 'No Piston endpoints' in str(e):
        raise SystemExit('Provide at least one Piston endpoint') from e
    raise

Prevention

When it happens

Trigger: PistonClient(base_endpoint=[]) constructed directly, or PISTON_ENDPOINTS set to an empty string / a value that splits into zero entries (e.g. PISTON_ENDPOINTS=','), bypassing the earlier None-check in get_piston_client_from_env.

Common situations: PISTON_ENDPOINTS='' in .env; a filtering step that removed all endpoints before constructing the client; programmatic construction passing an empty list after unhealthy-endpoint pruning.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of huggingface/open-r1@1416fa0cf2 (2026-08-30). Data as JSON: /api/errors/aa683c55451bd1bc. Report an issue: GitHub.