mudler/LocalAI · error · ValueError
Inline reward function '{name}' must return a list, got {typ
Error message
Inline reward function '{name}' must return a list, got {type(result).__name__} What it means
After exec'ing an inline reward, the backend smoke-tests it with func(["test"], answer=["test"]) and requires the return value to be a list (TRL's reward contract: one float per completion). Returning a scalar, numpy array, tuple, or None triggers this ValueError naming the actual type; note the 'must return a list' check re-raises even inside the broad except.
Source
Thrown at backend/python/trl/reward_functions.py:180
"re": re,
"math": math,
"json": json,
"string": string,
}
try:
compiled = compile(func_source, f"<inline-reward-{name}>", "exec")
except SyntaxError as e:
raise ValueError(f"Syntax error in inline reward function '{name}': {e}")
exec(compiled, restricted_globals)
func = restricted_globals[f"_user_reward_{name}"]
# Validate with a quick smoke test
try:
result = func(["test"], answer=["test"])
if not isinstance(result, list):
raise ValueError(
f"Inline reward function '{name}' must return a list, got {type(result).__name__}"
)
except Exception as e:
if "must return a list" in str(e):
raise
# Other errors during smoke test are acceptable (e.g. missing kwargs)
pass
return func
# ---------------------------------------------------------------------------
# Dispatcher
# ---------------------------------------------------------------------------
def build_reward_functions(specs_json):
"""Parse a JSON list of reward function specs and return a list of callables.
View on GitHub (pinned to 44413a9d06)
Solutions
- Return a list with one value per completion: return [score for c in completions].
- If using numpy, convert: return scores.tolist().
- Keep the length equal to len(completions); wrap accidental scalars as [value] only when there is exactly one completion.
Example fix
# before
def _user_reward_acc(c, **kw):
return 1.0 if c[0] == kw["answer"][0] else 0.0
# after
def _user_reward_acc(c, **kw):
return [1.0 if x == a else 0.0 for x, a in zip(c, kw["answer"])] Defensive patterns
Strategy: validation
Validate before calling
def reward_returns_list(func, sample=("test",)) -> bool:
try:
out = func(list(sample), answer=list(sample))
except Exception:
return True # smoke errors are tolerated by the backend
return isinstance(out, list) Type guard
from typing import Any, Callable
def is_list_returning_reward(f: Callable) -> bool:
out = f(["test"], answer=["test"])
return isinstance(out, list) Try / catch
try:
funcs = build_reward_functions(specs)
except ValueError as e:
if "must return a list" in str(e):
raise ConfigError("reward must return one float per completion") from e
raise Prevention
- Conform to TRL's contract: (completions, **kwargs) -> list[float] with len == len(completions).
- Call .tolist() on numpy results.
- Write a unit test per custom reward asserting list type and length.
When it happens
Trigger: Inline code returning sum(scores) instead of scores; returning a numpy array (isinstance(np.array, list) is False); early return None on an edge case; generator expression returned unmaterialized.
Common situations: Users porting reward code from single-sample scripts that returned one float; forgetting TRL batches completions.
Related errors
- Syntax error in inline reward function '{name}': {e}
- Inline reward function '{name}' has no code
- GRPO requires at least one reward function. Specify reward_f
- reward_funcs must be a JSON array of reward function specs
- Unknown builtin reward function '{name}'. Available: {availa
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/76a71ac81fd5e097.
Report an issue: GitHub.