BerriAI/litellm · error · CustomCodeCompilationError
Failed to compile custom code: {e}
Error message
Failed to compile custom code: {e} What it means
CustomCodeCompilationError raised when compiling/executing the sandboxed code raises anything other than a SyntaxError or a prior CustomCodeCompilationError — typically a runtime error thrown while exec() runs module-level statements, since compilation happens in two phases (compile, then exec in sandbox globals). The original exception is chained via raise ... from e and its message is embedded.
Source
Thrown at litellm/proxy/guardrails/guardrail_hooks/custom_code/custom_code_guardrail.py:188
The code runs in a sandboxed environment with only the allowed primitives.
"""
with self._compile_lock:
if self._compiled_function is not None:
return
try:
self._do_compile()
verbose_proxy_logger.debug("Custom code guardrail '%s' compiled successfully", self.guardrail_name)
except SyntaxError as e:
self._compile_error = f"Syntax error in custom code: {e}"
raise CustomCodeCompilationError(self._compile_error) from e
except CustomCodeCompilationError:
raise
except Exception as e:
self._compile_error = f"Failed to compile custom code: {e}"
raise CustomCodeCompilationError(self._compile_error) from e
@log_guardrail_information
async def apply_guardrail(
self,
inputs: GenericGuardrailAPIInputs,
request_data: dict,
input_type: Literal["request", "response"],
logging_obj: Optional["LiteLLMLoggingObj"] = None,
) -> GenericGuardrailAPIInputs:
"""
Apply the custom code guardrail to the inputs.
This method calls the user-defined apply_guardrail function and
processes its result to determine the appropriate action.
The user-defined function can be either sync or async:
- Sync: def apply_guardrail(inputs, request_data, input_type): ...
- Async: async def apply_guardrail(inputs, request_data, input_type): ...View on GitHub (pinned to 77b7c6c40c)
Solutions
- Read the embedded {e} — it names the exact exception and expression that failed during exec
- Move all logic inside def apply_guardrail; keep the module top level to declarations only
- Remove import statements — use only the primitives the sandbox provides (regex_match, http_get, http_post, block, allow, ...)
- Defer any expensive or environment-dependent computation to first call inside the entry function
Example fix
# before: import-time work fails inside the sandbox
import os
FLAG = os.environ.get('STRICT')
def apply_guardrail(inputs, request_data, input_type):
...
# after: declarative top level, lazy reads inside the entry point
def apply_guardrail(inputs, request_data, input_type):
strict = (request_data.get('metadata') or {}).get('strict', False)
if strict:
return block('strict mode')
return allow() Defensive patterns
Strategy: validation
Validate before calling
from litellm.proxy.guardrails.guardrail_hooks.custom_code.sandbox import (
build_sandbox_globals, compile_sandboxed,
)
def sandbox_preflight(custom_code: str) -> None:
g = build_sandbox_globals()
try:
exec(compile_sandboxed(custom_code), g)
except Exception as e:
raise ValueError(f'custom_code fails inside the sandbox: {type(e).__name__}: {e}') from e
assert callable(g.get('apply_guardrail')) Try / catch
from litellm.proxy.guardrails.guardrail_hooks.custom_code.custom_code_guardrail import CustomCodeCompilationError
try:
guardrail._compile_custom_code()
except CustomCodeCompilationError as e:
cause = e.__cause__ # the original module-level failure
raise SystemExit(f'custom_code rejected: {e} (caused by {cause!r})') from e Prevention
- Never put import statements or executable work at module level in custom_code - the sandbox has no __import__
- Run the exact sandbox preflight (same build_sandbox_globals/compile_sandboxed) in CI, not just python -m py_compile
- Keep top-level code declarative; compute inside apply_guardrail
When it happens
Trigger: Module-level code that executes during sandbox exec and fails: calling a bounds-checked limited builtin out of range (e.g. limited_range with a huge bound), NameError from an undefined name, TypeError while evaluating a class body, or accessing attributes the sandbox denies at exec time.
Common situations: Trying to import packages at module top (import os fails — the sandbox provides no __import__); module-level config reads or heavy computation that runs at import; code copied from a normal Python module that does work on import.
Related errors
- augmented assignment {op!r} is not supported
- Custom code must define an 'apply_guardrail' function. Expec
- 'apply_guardrail' must be a callable function
- Syntax error in custom code: {e}
- Unsupported HTTP method: {method}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/5ac321e7ef8fd5a7.
Report an issue: GitHub.