{"record":{"id":"14b664e52eea512f","repo":"flxzt/rnote","slug":"downcasting-svg-surface-content-failed-err-e","errorCode":null,"errorMessage":"Downcasting Svg surface content failed, Err: {e:?}","messagePattern":"Downcasting Svg surface content failed, Err: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/rnote-engine/src/svg.rs","lineNumber":139,"sourceCode":"        svg_surface.set_document_unit(cairo::SvgUnit::Px);\n\n        {\n            let cairo_cx = cairo::Context::new(&svg_surface)?;\n            // cairo only draws elements with positive coordinates, so we need to translate the content here\n            cairo_cx.translate(-bounds.mins[0], -bounds.mins[1]);\n            // apply the draw function\n            draw_func(&cairo_cx)?;\n        }\n\n        let content = String::from_utf8(\n            *svg_surface\n                .finish_output_stream()\n                .map_err(|e| {\n                    anyhow::anyhow!(\"Finishing Svg surface output stream failed, Err: {e:?}\")\n                })?\n                .downcast::<Vec<u8>>()\n                .map_err(|e| {\n                    anyhow::anyhow!(\"Downcasting Svg surface content failed, Err: {e:?}\")\n                })?,\n        )?;\n        let svg_data = rnote_compose::utils::remove_xml_header(&content);\n        let mut group = svg::node::element::Group::new().add(svg::node::Blob::new(svg_data));\n        // translate the content back to it's original position\n        group.assign(\n            \"transform\",\n            format!(\"translate({} {})\", bounds.mins[0], bounds.mins[1]),\n        );\n\n        Ok(Self {\n            svg_data: rnote_compose::utils::svg_node_to_string(&group)?,\n            bounds,\n        })\n    }\n\n    /// Generate an Svg with piet, using the `piet_cairo` backend and cairo's SvgSurface.\n    ///","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-engine/src/svg.rs#L121-L157","documentation":"Thrown by Svg::gen_with_cairo when the Box<dyn Any> returned by finish_output_stream() cannot be downcast to Vec<u8>. The stream backing the SVG surface must be the Vec<u8> originally supplied; a mismatch means the surface's stream is not the expected type.","triggerScenarios":"finish_output_stream() returns a Box<dyn Any> whose inner type differs from the Vec<u8> given to SvgSurface::for_stream — e.g. the stream was replaced via set_custom_output_stream or the surface came from another source.","commonSituations":"Refactoring code to use a custom output stream without updating the downcast, or reusing generic surface-finish helper code on a surface not created with a Vec<u8> stream.","solutions":["Ensure the SvgSurface was created with SvgSurface::for_stream(width, height, Vec::new()) and the stream was never swapped","Downcast to the actual stream type used (e.g. File) if a custom stream was set","Use downcast_ref first to inspect the concrete type when debugging"],"exampleFix":"// before\n.downcast::<Vec<u8>>().map_err(|e| anyhow::anyhow!(\"Downcasting Svg surface content failed, Err: {e:?}\"))?\n// after\nmatch stream.downcast::<Vec<u8>>() {\n    Ok(bytes) => bytes,\n    Err(any) => anyhow::bail!(\"unexpected stream type: {:?}\", any.type_id()),\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn is_vec_stream(any: &Box<dyn Any>) -> bool { any.is::<Vec<u8>>() }","tryCatchPattern":"let bytes = stream.downcast::<Vec<u8>>().map_err(|e| anyhow::anyhow!(\"stream type mismatch: {:?}\", e.type_id()))?;","preventionTips":["Always create SvgSurface::for_stream with a Vec<u8> and never replace it","Keep surface creation and stream finishing in the same function so types stay aligned"],"tags":["cairo","svg","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}