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

  1. Return a tuple from the code: 'return (times, values)' where times is your own numpy array
  2. Or add an input timeseries to the metric so the fallback reference time exists
  3. 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

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


AI-assisted analysis of commaai/openpilot@516ec1e682 (2026-08-15). Data as JSON: /api/errors/e4e0b812ec54dcd6. Report an issue: GitHub.