BerriAI/litellm · error · CustomCodeCompilationError
Custom code must define an 'apply_guardrail' function. Expec
Error message
Custom code must define an 'apply_guardrail' function. Expected signature: apply_guardrail(inputs, request_data, input_type)
What it means
CustomCodeCompilationError raised after the sandboxed custom code compiled and executed but no top-level apply_guardrail name exists in the execution globals. The custom-code guardrail contract requires an entry point with signature apply_guardrail(inputs, request_data, input_type); syntax-valid code that never defines it (or misspells it) fails here.
Source
Thrown at litellm/proxy/guardrails/guardrail_hooks/custom_code/custom_code_guardrail.py:156
@classmethod
def get_supported_event_hooks(cls) -> list[GuardrailEventHooks]:
return [
GuardrailEventHooks.pre_call,
GuardrailEventHooks.during_call,
GuardrailEventHooks.post_call,
GuardrailEventHooks.pre_mcp_call,
GuardrailEventHooks.during_mcp_call,
GuardrailEventHooks.logging_only,
]
def _do_compile(self) -> None:
"""Internal compilation method without lock. Expected to run inside _compile_lock."""
exec_globals: Final = build_sandbox_globals()
compiled: Final = compile_sandboxed(self.custom_code)
exec(compiled, exec_globals) # noqa: S102
if "apply_guardrail" not in exec_globals:
raise CustomCodeCompilationError(
"Custom code must define an 'apply_guardrail' function. "
"Expected signature: apply_guardrail(inputs, request_data, input_type)"
)
apply_fn: Final = exec_globals["apply_guardrail"]
if not callable(apply_fn):
raise CustomCodeCompilationError("'apply_guardrail' must be a callable function")
self._compiled_function = apply_fn
def _compile_custom_code(self) -> None:
"""
Compile the custom code and extract the apply_guardrail function.
The code runs in a sandboxed environment with only the allowed primitives.
"""
with self._compile_lock:
if self._compiled_function is not None:View on GitHub (pinned to 77b7c6c40c)
Solutions
- Define def apply_guardrail(inputs, request_data, input_type): at the top level of custom_code
- Check the exact spelling — singular, underscore-separated, case-sensitive
- Ensure every path in the function returns allow()/block(...)/modify(...) rather than falling through
Example fix
# before: wrong entry-point name
def check_prompts(inputs):
return allow()
# after
def apply_guardrail(inputs, request_data, input_type):
for text in inputs.get('texts') or []:
if 'secret-project' in text:
return block('confidential term detected')
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 preflight(custom_code: str) -> None:
g = build_sandbox_globals()
exec(compile_sandboxed(custom_code), g)
assert callable(g.get('apply_guardrail')), 'custom_code must define callable apply_guardrail(inputs, request_data, input_type)' Type guard
def has_entrypoint(exec_globals: dict) -> bool:
return callable(exec_globals.get('apply_guardrail')) Try / catch
from litellm.proxy.guardrails.guardrail_hooks.custom_code.custom_code_guardrail import CustomCodeCompilationError
try:
guardrail = CustomCodeGuardrail(guardrail_name='g', custom_code=src, event_hook='pre_call', default_on=True)
guardrail._compile_custom_code()
except CustomCodeCompilationError as e:
raise SystemExit(f'custom_code rejected: {e}') from e Prevention
- Run the sandbox preflight (compile + exec + callable check) in CI for every custom_code change
- Start from the documented template def apply_guardrail(inputs, request_data, input_type) and never rename it
When it happens
Trigger: custom_code defines the function under a different name (apply_guardrails plural, run_guardrail, check) or only defines helpers/constants; raised on first compile — at guardrail instantiation or on the first hooked request.
Common situations: Porting snippets from other frameworks with a different entry-point name; refactoring renames the function; generated code emits a differently named wrapper.
Related errors
- 'apply_guardrail' must be a callable function
- Custom code guardrail requires a guardrail_name
- Custom code guardrail requires 'custom_code' in litellm_para
- Syntax error in custom code: {e}
- Failed to compile custom code: {e}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/3d8b06fadff9cb89.
Report an issue: GitHub.