{"record":{"id":"d3c615b0aebfa16b","repo":"denoland/deno","slug":"failed-to-parse-profile-d3c615","errorCode":null,"errorMessage":"Failed to parse profile: {}","messagePattern":"Failed to parse profile: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"runtime/cpu_profiler/flamegraph.rs","lineNumber":22,"sourceCode":"use std::fs::File;\nuse std::io::BufWriter;\nuse std::io::Write;\n\nuse deno_core::serde_json;\n\nuse super::cpuprof::CpuProfile;\nuse super::cpuprof::ProfileNode;\n\nconst FLAMEGRAPH_JS: &str = include_str!(\"flamegraph.js\");\n\npub(crate) fn generate_flamegraph_svg(\n  profile: &serde_json::Value,\n  filepath: &std::path::Path,\n) -> std::io::Result<()> {\n  let profile: CpuProfile = match serde_json::from_value(profile.clone()) {\n    Ok(p) => p,\n    Err(err) => {\n      return Err(std::io::Error::new(\n        std::io::ErrorKind::InvalidData,\n        format!(\"Failed to parse profile: {}\", err),\n      ));\n    }\n  };\n\n  let node_map: HashMap<i32, &ProfileNode> =\n    profile.nodes.iter().map(|n| (n.id, n)).collect();\n\n  // Build parent map\n  let mut parent_map: HashMap<i32, i32> = HashMap::new();\n  for node in &profile.nodes {\n    for &child_id in &node.children {\n      parent_map.insert(child_id, node.id);\n    }\n  }\n\n  // Build folded stacks from samples","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/runtime/cpu_profiler/flamegraph.rs#L4-L40","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before (runtime/cpu_profiler/cpuprof.rs)\n#[derive(Deserialize)]\npub(crate) struct ProfileNode {\n  pub id: i32,\n  pub call_frame: CallFrame,\n  pub children: Vec<i32>,\n}\n\n// after — children may be absent for leaf nodes in some V8 versions\n#[derive(Deserialize)]\npub(crate) struct ProfileNode {\n  pub id: i32,\n  pub call_frame: CallFrame,\n  #[serde(default)]\n  pub children: Vec<i32>,\n}","handlingStrategy":"try-catch","validationCode":"// Same pre-check as the markdown path — validate the JSON shape first:\nfn looks_like_cpuprofile(v: &serde_json::Value) -> bool {\n  v.get(\"nodes\").map(|n| n.is_array()).unwrap_or(false)\n    && v.get(\"samples\").map(|n| n.is_array()).unwrap_or(false)\n    && v.get(\"timeDeltas\").map(|n| n.is_array()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"// Best-effort flamegraph, mirroring runtime/cpu_profiler/mod.rs:\nmatch flamegraph::generate_flamegraph_svg(&profile, &svg_path) {\n  Ok(()) => {}\n  Err(err) if err.kind() == std::io::ErrorKind::InvalidData => {\n    log::error!(\"flamegraph skipped: profile JSON rejected: {err}\");\n  }\n  Err(err) => log::error!(\"flamegraph write failed: {err}\"),\n}","preventionTips":["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."],"tags":["cpu-profiler","flamegraph","serde","deserialization","v8","runtime"],"backgroundTag":"json-deserialize-schema-mismatch","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}