{"record":{"id":"bdf51e12da29bb5b","repo":"linera-io/linera-protocol","slug":"failed-to-parse-snap-body-in-path-as-formats","errorCode":null,"errorMessage":"failed to parse SNAP body in {path:?} as Formats: {e}","messagePattern":"failed to parse SNAP body in (.+?) as Formats: (.+?)","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"linera-client/src/client_context.rs","lineNumber":971,"sourceCode":"\n/// Reads an insta SNAP file containing a YAML-encoded `Formats` value and parses\n/// it. The caller BCS-serializes the result to obtain the application formats\n/// blob payload: BCS matches the documented intent (the blob is \"the BCS\n/// serialization of an application's `Formats`\") and the encoding the explorer\n/// decodes with.\n#[cfg(feature = \"fs\")]\nfn load_formats_from_snap(path: &std::path::Path) -> Result<linera_sdk::formats::Formats, Error> {\n    let content = fs::read_to_string(path).map_err(|e| {\n        std::io::Error::new(e.kind(), format!(\"failed to read SNAP file {path:?}: {e}\"))\n    })?;\n    let body = strip_snap_frontmatter(&content).ok_or_else(|| {\n        std::io::Error::new(\n            std::io::ErrorKind::InvalidData,\n            format!(\"SNAP file {path:?} is missing the `---` frontmatter delimiters\"),\n        )\n    })?;\n    let formats = serde_yaml_08::from_str(body).map_err(|e| {\n        std::io::Error::new(\n            std::io::ErrorKind::InvalidData,\n            format!(\"failed to parse SNAP body in {path:?} as Formats: {e}\"),\n        )\n    })?;\n    Ok(formats)\n}\n\n#[cfg(feature = \"fs\")]\nfn strip_snap_frontmatter(content: &str) -> Option<&str> {\n    let rest = content.strip_prefix(\"---\\n\")?;\n    let end = rest.find(\"\\n---\\n\")?;\n    Some(&rest[end + \"\\n---\\n\".len()..])\n}\n\n#[cfg(not(web))]\nimpl<Env: Environment> ClientContext<Env> {\n    /// Prepares the chains and fungible tokens needed to run a benchmark.\n    pub async fn prepare_for_benchmark(","sourceCodeStart":953,"sourceCodeEnd":989,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-client/src/client_context.rs#L953-L989","documentation":"After stripping the frontmatter, load_formats_from_snap deserializes the remaining YAML body into linera_sdk::formats::Formats with serde_yaml_08. This error means the delimiters were fine but the YAML inside is either syntactically invalid or does not match the Formats schema (wrong field names, wrong types, missing required fields). The message includes the path and serde_yaml's parse/deserialize cause.","triggerScenarios":"Passing --formats a .snap whose body is not valid YAML (tabs for indentation, a stray quote or colon, duplicated keys), or valid YAML that does not deserialize as Formats (renamed/removed fields, wrong nesting, a value of the wrong type for a version/encoding field). It fires after the frontmatter check succeeded.","commonSituations":"Editing a generated .snap by hand and breaking indentation; snapshots produced by an older/newer linera-version of Formats whose schema changed (field renames, added required entries); copying only part of a snapshot; merging snapshots with duplicate keys; YAML gotchas like unquoted strings starting with special characters or tabs pasted from a browser.","solutions":["Read the {e} cause in the message: a scan error points at a line/column to fix (tabs -> spaces, stray quote); a deserialize error names the offending field — rename or retype it to match Formats.","Regenerate the snapshot with the linera-version you are publishing from (run the application's tests with that toolchain) so the body matches the current Formats schema, instead of hand-patching an old .snap.","If you must edit, validate with serde_yaml 0.8 semantics (plain YAML 1.1/1.2 basics, LF, two-space indent) and compare field-for-field against a known-good snapshot in the same repo."],"exampleFix":"# before (body inside the snap; breaks on tab indent / unknown field)\n---\nsource: format.rs\n---\n\tformats:   # tab indentation -> YAML scan error\n\n# after\n---\nsource: format.rs\n---\nformats:\n  - ...\n","handlingStrategy":"validation","validationCode":"fn snap_body_parses(content: &str) -> bool {\n    let rest = content.strip_prefix(\"---\\n\")?;\n    let end = rest.find(\"\\n---\\n\")?;\n    serde_yaml_08::from_str::<linera_sdk::formats::Formats>(&rest[end + 5..]).is_ok()\n}\n// (make it return bool by mapping Option->false in the caller)","typeGuard":"fn is_parsable_formats(yaml_body: &str) -> bool {\n    serde_yaml_08::from_str::<serde_yaml_08::Value>(yaml_body).is_ok()\n}","tryCatchPattern":"match load_formats_from_snap(path) {\n    Ok(f) => f,\n    Err(e) if e.to_string().contains(\"failed to parse SNAP body\") => {\n        anyhow::bail!(\"SNAP {path:?} body is not a valid Formats YAML: {e}; regenerate the snapshot\")\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Regenerate snapshots with the same linera version you publish with, so schema and body always match.","Never hand-edit generated .snap bodies; change the source of truth and let insta rewrite the snapshot.","Add a CI lint that parses every .snap used for --formats with serde_yaml_08 before the publish job."],"tags":["rust","yaml","linera","deserialization","snapshot"],"backgroundTag":"yaml-parse-error","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}