commaai/openpilot · error · ValueError
No reference series found. Set an input timeseries or return
Error message
No reference series found. Set an input timeseries or return (times, values).
What it means
After evaluating the user's code, math_eval needs a time axis. If the result is not a (times, values) tuple, it falls back to the times of the first input series (series_t[first_path]). When no input series was supplied (first_path is None), there is no reference timebase and the output cannot be written, so it raises this ValueError.
Source
Thrown at openpilot/tools/jotpluggler/math_eval.py:124
env[f"v{i}"] = series_v[path]
else:
env[f"t{i}"] = reference_time
env[f"v{i}"] = _resample_to_reference(reference_time, series_t[path], series_v[path])
with open(globals_path, encoding="utf-8") as f:
globals_code = f.read()
if globals_code.strip():
exec(globals_code, env, env)
with open(code_path, encoding="utf-8") as f:
user_code = f.read()
result = _evaluate_user_code(user_code, env)
if isinstance(result, tuple) and len(result) == 2:
result_t, result_v = result
else:
if first_path is None:
raise ValueError("No reference series found. Set an input timeseries or return (times, values).")
result_t = series_t[first_path]
result_v = result
result_t = np.asarray(result_t, dtype=np.float64).reshape(-1)
result_v = np.asarray(result_v, dtype=np.float64).reshape(-1)
if result_t.size == 0 or result_v.size == 0:
raise ValueError("Custom series returned an empty result")
if result_t.shape != result_v.shape:
raise ValueError(f"Time/value arrays must have the same shape, got {result_t.shape} and {result_v.shape}")
_write_vector(out_t_path, result_t)
_write_vector(out_v_path, result_v)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())View on GitHub (pinned to 516ec1e682)
Solutions
- Return a tuple from the code: 'return (times, values)' where times is your own numpy array
- Or add an input timeseries to the metric so the fallback reference time exists
- Check the metric's input keys resolve to real series (first_path should not be None)
Example fix
# before return np.linspace(0, 1, 100) ** 2 # after times = np.arange(100) / 100.0 return (times, times ** 2)
Defensive patterns
Strategy: validation
Validate before calling
if not isinstance(result, tuple) and first_path is None:
raise SystemExit("metric returns a bare value but defines no input series; return (times, values)") Type guard
def is_timeseries_pair(result) -> bool:
"""True when result is a (times, values) pair of array-likes."""
return isinstance(result, tuple) and len(result) == 2 Try / catch
try:
result = _evaluate_user_code(user_code, env)
except ValueError as e:
if 'No reference series' in str(e):
raise SystemExit('add an input timeseries to the metric or return (times, values)')
raise Prevention
- For metrics with no inputs, always return an explicit (times, values) tuple
- Validate metric configs (inputs present OR tuple-returning code) at load time
When it happens
Trigger: Running a metric whose code returns a plain value/array while the metric defines no input timeseries; inputs declared but none resolved to actual paths; user intended to return a tuple but returned only the values array.
Common situations: Generating a constant or computed-from-scratch series without binding an input; misconfigured metric inputs (wrong keys) so first_path stays None; refactor that dropped the input list.
Related errors
- Custom series returned an empty result
- Function body is empty
- Time/value arrays must have the same shape, got {result_t.sh
- invalid config backup: {backup}
- No camera file for segment {seg_idx}
AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15).
Data as JSON: /api/errors/e4e0b812ec54dcd6.
Report an issue: GitHub.