huggingface/open-r1 · error · PistonError
Server error. status={status}. {res_json}
Error message
Server error. status={status}. {res_json} What it means
PistonClient.send_execute raises PistonError('Server error. status=...') when the Piston worker's /execute HTTP endpoint returns a status code other than 200. The response body (res_json) is included in the message to surface the server's own error description. It signals a server-side rejection such as bad payload, rate limiting, or gateway errors.
Source
Thrown at src/open_r1/utils/competitive_programming/piston_client.py:160
base_delay = 1.0
status = None
endpoint = None
for attempt in range(max_retries + 1):
try:
endpoint = await self._wait_for_endpoint()
if attempt > 0:
await asyncio.sleep(1)
async with self.session.post(
f"{endpoint.rstrip('/')}/execute", json=data, headers={"Content-Type": "application/json"}
) as response:
status = response.status
res_json = await response.json(content_type=None)
if status != 200:
raise PistonError(f"Server error. status={status}. {res_json}")
if res_json is None:
raise PistonError(f"Empty response. status={status}")
# piston overloaded
if "run" in res_json and "Resource temporarily unavailable" in res_json["run"].get("stderr", ""):
raise PistonError(f"Piston overloaded: {res_json['run']['stderr']}")
return res_json
except (PistonError, asyncio.TimeoutError, aiohttp.ClientConnectionError, RuntimeError) as e:
# Only retry if we haven't reached max retries yet
if attempt < max_retries:
# Calculate backoff with jitter
delay = min(base_delay * (2**attempt), 10) # Exponential backoff, capped at 10 seconds
jitter = delay * 0.2 * (2 * asyncio.get_event_loop().time() % 1 - 0.5) # Add ±10% jitter
retry_delay = delay + jitter
print(f"Retrying in {retry_delay:.2f} seconds [{self.endpoint_ids[endpoint]}] {endpoint} - {e}")
# special case: worker died
if isinstance(e, aiohttp.ClientConnectionError) and "Connect call failed" in str(e):View on GitHub (pinned to 1416fa0cf2)
Solutions
- Read the status and body in the message to identify the server-side cause
- Verify the piston endpoint URL is reachable and points at /api/v2 (curl {endpoint}/api/v2/runtimes)
- Check Piston worker logs/health; restart or scale workers if 502/503/429
- Fix the execute payload (language, version, files) if status is 400
- Increase max_retries or add client-side pacing if hitting rate limits
Example fix
// before client = PistonClient(base_endpoints=["http://piston:2000"]) # 404 on /execute // after client = PistonClient(base_endpoints=["http://piston:2000/api/v2"])
Defensive patterns
Strategy: retry
Validate before calling
import aiohttp
async def endpoint_ok(url):
try:
async with aiohttp.ClientSession() as s:
async with s.get(f"{url.rstrip('/')}/runtimes", timeout=aiohttp.ClientTimeout(total=5)) as r:
return r.status == 200
except Exception:
return False Type guard
def is_http_ok(status, body):
return isinstance(status, int) and status == 200 and isinstance(body, dict) Try / catch
try:
res = await client.send_execute(data)
except PistonError as e:
if str(e).startswith("Server error"):
logger.warning("Piston HTTP failure, falling back: %s", e)
res = run_locally(data) # or requeue
else:
raise Prevention
- Health-check endpoints (/runtimes) before executing and drop unhealthy ones
- Keep the API path correct (/api/v2) in endpoint configuration
- Monitor worker 5xx/429 rates and scale the Piston fleet
- Set a sane max_retries and alert when retries are exhausted
When it happens
Trigger: POST to {endpoint}/execute returns 4xx/5xx (e.g. 400 malformed payload, 429 rate limit, 502/503 gateway down, 404 wrong endpoint URL). The client retries up to max_retries (default 5) with exponential backoff before giving up.
Common situations: Misconfigured PISTON_ENDPOINT_URL (missing /api/v2 path, wrong port), Piston worker overloaded or restarting behind a load balancer, payload with invalid fields (bad language version), reverse proxy returning HTML error pages.
Related errors
AI-assisted analysis of huggingface/open-r1@1416fa0cf2 (2026-08-30).
Data as JSON: /api/errors/a853a5d91ce0c1c8.
Report an issue: GitHub.