High severity intermediate · Fix: 5-15 min

RuntimeError

RuntimeError: no running event loop (Guardrails AsyncGuard context)

What this error means
Guardrails AsyncGuard is called from a synchronous context (no active asyncio event loop), causing a RuntimeError when the guard tries to execute async validators.

Stack trace

traceback
Traceback (most recent call last):
  File "your_script.py", line 42, in <module>
    validated_output = guard.validate(response)
  File "/site-packages/guardrails/guard.py", line 156, in validate
    return self._run_validators(data)
  File "/site-packages/guardrails/validators/async_validator.py", line 89, in _run_validators
    loop = asyncio.get_running_loop()
RuntimeError: no running event loop
QUICK FIX
Wrap guard.validate(response) in asyncio.run(guard.validate(response)) if called from sync script, or convert the calling function to async and await the validation.

Why it happens

Guardrails AsyncGuard validators (like async LLM calls or async I/O checks) require an active asyncio event loop to execute. When you call guard.validate() from a synchronous function or main thread without an event loop, asyncio.get_running_loop() fails because no loop is running. This happens most often when mixing async guards with synchronous LLM chains (like OpenAI SDK v1 client.chat.completions.create() which is blocking) or when guards are used in non-async contexts like FastAPI request handlers without proper async/await wrapping.

Detection

Check your code for guard.validate() calls at the top level of scripts or inside synchronous functions without @asyncio.coroutine or async def wrappers. Inspect your guard definition: if it uses async validators like ValidJson(async_check=True) or custom async validators, but guard.validate() is called synchronously, you have a mismatch. Add logging before the validate() call to confirm it's being called in a sync context.

Causes & fixes

1

Guard with async validators is called from a synchronous script or function with no event loop running

✓ Fix

Wrap the guard.validate() call in asyncio.run() if in a script, or make the entire calling function async and await the validation. Use guard.validate(response, async_mode=True) if your guard supports it, or switch to synchronous validators only.

2

FastAPI/async framework request handler calls guard synchronously inside async endpoint

✓ Fix

Mark the endpoint as async (async def) and use await guard.validate(response) if your guard has an async validate method. Alternatively, run guard.validate() in a thread pool using asyncio.to_thread(guard.validate, response) to avoid blocking the event loop.

3

Guard definition includes async validators but validate() is called from OpenAI SDK sync call without event loop setup

✓ Fix

Either (1) remove async validators and use only sync validators, or (2) wrap the entire OpenAI call + guard validation in asyncio.run(validate_response(response)) where validate_response is an async function, or (3) use the async OpenAI client (AsyncOpenAI) and await both the call and validation together.

4

Jupyter notebook or interactive session calling guard.validate() without asyncio context

✓ Fix

Use nest_asyncio.apply() at the top of your notebook, then wrap validate() in asyncio.run(). Or use IPython's magic command %gui asyncio to enable event loop in the notebook kernel.

Code: broken vs fixed

Broken - triggers the error
python
import os
from openai import OpenAI
from guardrails import Guard
from guardrails.hub import ValidJson

# Initialize guard with async validator
guard = Guard().use(ValidJson, on_fail='exception')
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))

# This is called synchronously with NO event loop running
response = client.chat.completions.create(
    model='gpt-4o-mini',
    messages=[{'role': 'user', 'content': 'Return valid JSON'}]
)

# This line triggers RuntimeError: no running event loop
validated = guard.validate(response.choices[0].message.content)  # ← EVENT LOOP ERROR HERE
print(validated)
Fixed - works correctly
python
import os
import asyncio
from openai import OpenAI
from guardrails import Guard
from guardrails.hub import ValidJson

# Initialize guard with async validator
guard = Guard().use(ValidJson, on_fail='exception')
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))

# Define async validation function
async def validate_response(text):
    # Now called inside an active event loop
    validated = guard.validate(text)
    return validated

# Synchronous script - wrap async call with asyncio.run()
response = client.chat.completions.create(
    model='gpt-4o-mini',
    messages=[{'role': 'user', 'content': 'Return valid JSON'}]
)

# FIXED: Use asyncio.run() to create event loop for the async validation
validated = asyncio.run(validate_response(response.choices[0].message.content))
print(f'Validated output: {validated}')
Wrapped the guard.validate() call in an async function and used asyncio.run() to create and manage the event loop, ensuring the async validators have a running loop to execute in.

Workaround

If you cannot refactor to async, replace async validators with synchronous equivalents. For example, use ValidJson() without async options, or implement custom synchronous validators. Alternatively, move guard validation to a background task or separate async worker process that manages its own event loop, and return results via a queue or database.

Prevention

Design your validation pipeline to match your execution context: (1) Use only synchronous validators if your app is synchronous, (2) Use asyncio.run() at the entry point of scripts to establish a single event loop for the entire program, (3) In async frameworks like FastAPI, mark endpoints async and await validation calls, (4) Use asyncio.to_thread() to offload sync guards from async contexts without blocking the loop, (5) Test guards in their actual deployment context (script vs web framework) during development.

Python 3.9+ · guardrails-ai >=0.4.0 · tested on 0.5.x
Verified 2026-04
Verify ↗

Community Notes

No notes yetBe the first to share a version-specific fix or tip.