jax-ml/jax · warning · ValueError

Invalid trace folder: {latest_trace_folder}

Error message

Invalid trace folder: {latest_trace_folder}

What it means

When creating a Perfetto trace file, JAX globs `*.trace.json.gz` in the newest profile folder under log_dir/plugins/profile. If that folder doesn't contain exactly one such file, the tuple-unpack fails and is re-raised as 'Invalid trace folder'.

Source

Thrown at jax/_src/profiler.py:221

        set_metadata(f"{backend.platform}_version", backend.platform_version)
      except RuntimeError:
        pass
    _profile_state.profile_session = _profiler.ProfilerSession(options)
    _profile_state.create_perfetto_link = create_perfetto_link
    _profile_state.create_perfetto_trace = (
        create_perfetto_trace or create_perfetto_link)
    _profile_state.log_dir = str(log_dir)


def _write_perfetto_trace_file(log_dir: os.PathLike | str):
  # Navigate to folder with the latest trace dump to find `trace.json.jz`
  trace_folders = (pathlib.Path(log_dir).absolute() / "plugins" / "profile").iterdir()
  latest_trace_folder = max(trace_folders, key=os.path.getmtime)
  trace_jsons = latest_trace_folder.glob("*.trace.json.gz")
  try:
    trace_json, = trace_jsons
  except ValueError as value_error:
    raise ValueError(f"Invalid trace folder: {latest_trace_folder}") from value_error

  logger.info("Loading trace.json.gz and removing its metadata...")
  # Perfetto doesn't like the `metadata` field in `trace.json` so we remove
  # it.
  # TODO(sharadmv): speed this up by updating the generated `trace.json`
  # to not include metadata if possible.
  with gzip.open(trace_json, "rb") as fp:
    trace = json.load(fp)
    del trace["metadata"]
  perfetto_trace = latest_trace_folder / "perfetto_trace.json.gz"
  logger.info("Writing perfetto_trace.json.gz...")
  with gzip.open(perfetto_trace, "w") as fp:
    fp.write(json.dumps(trace).encode("utf-8"))
  return perfetto_trace

class _PerfettoServer(http.server.SimpleHTTPRequestHandler):
  """Handles requests from `ui.perfetto.dev` for the `trace.json`"""

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Inspect the newest folder under <log_dir>/plugins/profile and remove corrupt/duplicate artifacts, then re-profile
  2. Re-run the full start_trace/stop_trace cycle cleanly
  3. Disable create_perfetto_trace if you only need the raw profile files

Example fix

# before
jax.profiler.start_trace('/tmp/log', create_perfetto_trace=True)
... 
jax.profiler.stop_trace()  # folder has no trace.json.gz
# after
jax.profiler.start_trace('/tmp/log')
jax.profiler.stop_trace()
Defensive patterns

Strategy: validation

Validate before calling

import pathlib, os
log_dir = pathlib.Path('/tmp/log')
folders = (log_dir/'plugins'/'profile').iterdir()
latest = max(folders, key=os.path.getmtime)
traces = list(latest.glob('*.trace.json.gz'))
assert len(traces) == 1, f'expected 1 trace file, found {len(traces)}'

Try / catch

try:
    jax.profiler.stop_trace()
except ValueError as e:
    if 'Invalid trace folder' in str(e):
        # raw profile still exists; skip perfetto generation
        pass
    else:
        raise

Prevention

When it happens

Trigger: Calling stop_trace with `create_perfetto_trace=True` when the latest profile folder has zero or multiple trace.json.gz files — e.g. a partially written export, a crashed session, or a stale/corrupt folder.

Common situations: Interrupted profiling runs; multiple profile outputs colliding in one folder; permissions or disk-full issues preventing the trace.json.gz write; log_dir pointed at a directory with hand-created folders.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/31462158ac120c6a. Report an issue: GitHub.