denoland/deno · error
Failed to parse profile: {}
Error message
Failed to parse profile: {} What it means
The flamegraph path of the CPU profiler (runtime/cpu_profiler/flamegraph.rs) deserializes the same profile JSON into `CpuProfile` before building the node/parent maps for the SVG. On serde failure it wraps the error as `io::ErrorKind::InvalidData` with this message. Like the markdown report, the flamegraph is generated after the raw `.cpuprofile` was already flushed, so only the `.svg` artifact is lost; the caller in mod.rs logs and continues.
Source
Thrown at runtime/cpu_profiler/flamegraph.rs:22
use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use deno_core::serde_json;
use super::cpuprof::CpuProfile;
use super::cpuprof::ProfileNode;
const FLAMEGRAPH_JS: &str = include_str!("flamegraph.js");
pub(crate) fn generate_flamegraph_svg(
profile: &serde_json::Value,
filepath: &std::path::Path,
) -> std::io::Result<()> {
let profile: CpuProfile = match serde_json::from_value(profile.clone()) {
Ok(p) => p,
Err(err) => {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("Failed to parse profile: {}", err),
));
}
};
let node_map: HashMap<i32, &ProfileNode> =
profile.nodes.iter().map(|n| (n.id, n)).collect();
// Build parent map
let mut parent_map: HashMap<i32, i32> = HashMap::new();
for node in &profile.nodes {
for &child_id in &node.children {
parent_map.insert(child_id, node.id);
}
}
// Build folded stacks from samplesView on GitHub (pinned to 9ad36f7a2c)
Solutions
- Read the serde detail in the message to find the offending field, then fix the `CpuProfile`/`ProfileNode` structs in runtime/cpu_profiler/cpuprof.rs (both report generators share them, so one fix repairs markdown and flamegraph).
- Add `#[serde(default)]` for fields that may be absent (empty samples/time deltas on tiny profiles).
- Use the raw `.cpuprofile` (still written successfully) in speedscope or Chrome DevTools as an immediate workaround.
Example fix
// before (runtime/cpu_profiler/cpuprof.rs)
#[derive(Deserialize)]
pub(crate) struct ProfileNode {
pub id: i32,
pub call_frame: CallFrame,
pub children: Vec<i32>,
}
// after — children may be absent for leaf nodes in some V8 versions
#[derive(Deserialize)]
pub(crate) struct ProfileNode {
pub id: i32,
pub call_frame: CallFrame,
#[serde(default)]
pub children: Vec<i32>,
} Defensive patterns
Strategy: try-catch
Validate before calling
// Same pre-check as the markdown path — validate the JSON shape first:
fn looks_like_cpuprofile(v: &serde_json::Value) -> bool {
v.get("nodes").map(|n| n.is_array()).unwrap_or(false)
&& v.get("samples").map(|n| n.is_array()).unwrap_or(false)
&& v.get("timeDeltas").map(|n| n.is_array()).unwrap_or(false)
} Try / catch
// Best-effort flamegraph, mirroring runtime/cpu_profiler/mod.rs:
match flamegraph::generate_flamegraph_svg(&profile, &svg_path) {
Ok(()) => {}
Err(err) if err.kind() == std::io::ErrorKind::InvalidData => {
log::error!("flamegraph skipped: profile JSON rejected: {err}");
}
Err(err) => log::error!("flamegraph write failed: {err}"),
} Prevention
- Both report generators share the `CpuProfile` structs in cpuprof.rs — fix schema drift once and both recover.
- Smoke-test flamegraph generation after V8 upgrades with a tiny scripted workload.
- Keep external `.cpuprofile` files unmodified (don't merge/rewrite them with third-party tools) before feeding the flamegraph generator.
When it happens
Trigger: Enabling flamegraph generation on a profile whose JSON does not match `CpuProfile` — same root causes as the markdown variant: schema drift after a V8 upgrade, missing `nodes`/`samples`/`timeDeltas` keys, or value type mismatches (e.g. a string where an i32 node id is expected).
Common situations: V8 profile-format changes between versions; profiles captured under unusual conditions (extremely short runs, no samples); post-processing or merging `.cpuprofile` files with external tools that alter the JSON shape.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse profile: {}
- ReadRawBytes() failed
- cannot use non-object value with an internally tag enum
- buffer must be a TypedArray or a DataView
- source must be a TypedArray or a DataView
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/d3c615b0aebfa16b.
Report an issue: GitHub.