RuntimeError
RuntimeError: no running event loop (Guardrails AsyncGuard context)
Stack trace
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 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
Guard with async validators is called from a synchronous script or function with no event loop running
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.
FastAPI/async framework request handler calls guard synchronously inside async endpoint
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.
Guard definition includes async validators but validate() is called from OpenAI SDK sync call without event loop setup
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.
Jupyter notebook or interactive session calling guard.validate() without asyncio context
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
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) 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}') 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.