mudler/LocalAI · error · ValueError
reward_funcs must be a JSON array of reward function specs
Error message
reward_funcs must be a JSON array of reward function specs
What it means
build_reward_functions accepts the reward spec either as a pre-parsed list or as a JSON string; after json.loads (or direct use), the top level must be a JSON array. Passing a single object, a dict, or a double-encoded JSON string ('\"[...]\"' which loads to a str) fails this isinstance check.
Source
Thrown at backend/python/trl/reward_functions.py:211
# Dispatcher
# ---------------------------------------------------------------------------
def build_reward_functions(specs_json):
"""Parse a JSON list of reward function specs and return a list of callables.
Each spec is a dict with:
- type: "builtin" or "inline"
- name: function name
- code: (inline only) Python function body
- params: (optional) dict of string params applied via functools.partial
"""
if isinstance(specs_json, str):
specs = json.loads(specs_json)
else:
specs = specs_json
if not isinstance(specs, list):
raise ValueError("reward_funcs must be a JSON array of reward function specs")
reward_funcs = []
for spec in specs:
spec_type = spec.get("type", "builtin")
name = spec.get("name", "")
params = spec.get("params", {})
if spec_type == "builtin":
if name not in BUILTIN_REGISTRY:
available = ", ".join(sorted(BUILTIN_REGISTRY.keys()))
raise ValueError(
f"Unknown builtin reward function '{name}'. Available: {available}"
)
func = BUILTIN_REGISTRY[name]
if params:
# Convert string params to appropriate types
typed_params = {}
for k, v in params.items():View on GitHub (pinned to 44413a9d06)
Solutions
- Wrap the spec in a list: '[{"type":"builtin","name":"format_reward"}]'.
- If constructing programmatically, pass the Python list directly (build_reward_functions accepts both) instead of ad-hoc string building.
- Validate with json.loads(spec) in a unit test and assert isinstance(result, list).
Example fix
# before
extra["reward_funcs"] = json.dumps({"type": "builtin", "name": "format_reward"})
# after
extra["reward_funcs"] = json.dumps([{ "type": "builtin", "name": "format_reward" }]) Defensive patterns
Strategy: validation
Validate before calling
import json
def reward_specs_valid(specs) -> bool:
parsed = json.loads(specs) if isinstance(specs, str) else specs
return isinstance(parsed, list) Type guard
def is_reward_spec_list(x) -> bool:
import json
p = json.loads(x) if isinstance(x, str) else x
return isinstance(p, list) and all(isinstance(s, dict) for s in p) Try / catch
try:
build_reward_functions(extra["reward_funcs"])
except ValueError as e:
if "JSON array" in str(e):
extra["reward_funcs"] = json.dumps([json.loads(extra["reward_funcs"])])
retry
raise Prevention
- Always pass the Python list (or json.dumps(list)) — never dicts or double-encoded strings.
- Schema-validate extra_options in client SDKs.
- Add a JSON schema for reward specs to your API docs.
When it happens
Trigger: extra_options['reward_funcs'] = '{\"type\": ...}' (single object, not array); reward_funcs='\"[ {...} ]\"' (JSON string of a JSON string); passing a bare function name string like 'format_reward'.
Common situations: Building the extra_options dict in code and forgetting json.dumps of the list; hand-writing JSON in YAML model configs; clients that stringify twice.
Related errors
- Unknown builtin reward function '{name}'. Available: {availa
- Inline reward function '{name}' has no code
- Unknown reward function type '{spec_type}'. Use 'builtin' or
- GRPO requires at least one reward function. Specify reward_f
- Unsupported training method: {training_method}. Supported: s
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/9f55212b2fe60811.
Report an issue: GitHub.