sgl-project/sglang · error · Exception
Trace file is empty.
Error message
Trace file is empty.
What it means
rpd_to_chrome_trace opens the ROCm RPD profiling database and queries MIN(start) from rocpd_api; a NULL result means the API-event table has no rows, i.e. the captured profile contains no kernel/API activity, so conversion cannot proceed.
Source
Thrown at python/sglang/srt/utils/rpd_utils.py:72
',{"name":"thread_name","ph":"M","pid":"%s","tid":"%s","args":{"name":"%s"}}\n'
% (row[0], row[1], "HSA " + str(row[1]))
)
outfile.write(
',{"name":"thread_sort_index","ph":"M","pid":"%s","tid":"%s","args":{"sort_index":"%s"}}\n'
% (row[0], row[1], row[1] * 2 - 1)
)
except ValueError:
outfile.write("")
except:
pass
rangeStringApi = ""
rangeStringOp = ""
rangeStringMonitor = ""
min_time = connection.execute("select MIN(start) from rocpd_api;").fetchall()[0][0]
max_time = connection.execute("select MAX(end) from rocpd_api;").fetchall()[0][0]
if min_time is None:
raise Exception("Trace file is empty.")
print("Timestamps:")
print(f"\t first: \t{min_time/1000} us")
print(f"\t last: \t{max_time/1000} us")
print(f"\t duration: \t{(max_time-min_time) / 1000000000} seconds")
start_time = min_time / 1000
end_time = max_time / 1000
if start:
if "%" in start:
start_time = (
(max_time - min_time) * (int(start.replace("%", "")) / 100) + min_time
) / 1000
else:
start_time = int(start)
rangeStringApi = "where rocpd_api.start/1000 >= %s" % (start_time)
rangeStringOp = "where rocpd_op.start/1000 >= %s" % (start_time)View on GitHub (pinned to 0132848349)
Solutions
- Re-profile with a wider window: ensure GPU work occurs between start and stop
- Verify with sqlite3 <file> 'select count(*) from rocpd_api;' that events exist before converting
- Check the RPD/ROCprofiler capture configuration actually enabled API/kernel records
- Discard empty runs and only convert DBs with nonzero event counts
Example fix
# before
rpd_to_chrome_trace('empty.rpd') # Exception: Trace file is empty.
# after
import sqlite3
if sqlite3.connect('run.rpd').execute('select count(*) from rocpd_api').fetchone()[0] > 0:
rpd_to_chrome_trace('run.rpd') Defensive patterns
Strategy: validation
Validate before calling
import sqlite3
def rpd_has_events(path: str) -> bool:
con = sqlite3.connect(path)
try:
return con.execute('select count(*) from rocpd_api').fetchone()[0] > 0
finally:
con.close() Type guard
null
Try / catch
try:
rpd_to_chrome_trace(path)
except Exception as e:
if 'Trace file is empty' in str(e):
logger.warning('empty RPD capture %s; skipping conversion', path) Prevention
- Ensure GPU work runs within the profiler window
- Pre-check rocpd_api row counts before converting
- Discard zero-event captures in batch conversion scripts
When it happens
Trigger: Calling rpd_to_chrome_trace on an RPD sqlite file produced by a profiling session that recorded nothing — profiler started and stopped before work ran, wrong pass/iteration range, or capture failed silently.
Common situations: Short-lived benchmarks where the profiler window misses all kernels; RPD tool version/config capturing zero API records; converting placeholder DBs.
Related errors
- No trace files found for profile_id: {self.profile_id}
- --enable-hisparse is not supported with the unified-KV path
- {self.quantization} quantization is currently not supported
- Decode context parallel (decode_context_parallel_size > 1) i
- KV4 is not tested on non-CUDA platforms.
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/27988ce21e4377c5.
Report an issue: GitHub.