flxzt/rnote · error

Creating svg surface with dimensions

Error message

Creating svg surface with dimensions ({width}, {height}) failed, Err: {e:?}

What it means

svg::gen_with_cairo creates a cairo::SvgSurface writing to an in-memory stream using the extents of the given bounds; if cairo fails to create the surface (invalid dimensions, out-of-memory, or a cairo internal error), the Result is Err and this message wraps it. Bounds are asserted valid first, so failures here are typically dimensional or cairo-level.

Solutions

  1. Clamp/validate width and height to a sane range (> 0 and within cairo limits) before creating the surface
  2. Sanity-check bounds for NaN/infinity before calling gen_with_cairo
  3. Tile the export into multiple smaller SVG surfaces if the extents exceed limits
  4. Inspect the wrapped {e:?} for cairo's specific status code to confirm the cause

Example fix

// before
let width = bounds.extents()[0];
let height = bounds.extents()[1];
let surface = cairo::SvgSurface::for_stream(width, height, Vec::new())?;
// after
let (width, height) = (bounds.extents()[0], bounds.extents()[1]);
if !(width.is_finite() && height.is_finite() && width > 0.0 && height > 0.0 && width < 32767.0 && height < 32767.0) {
    return Err(anyhow!("unsupported svg export size: {width}x{height}"));
}
let surface = cairo::SvgSurface::for_stream(width, height, Vec::new())?;
Defensive patterns

Strategy: validation

Validate before calling

let (w, h) = (bounds.extents()[0], bounds.extents()[1]);
if !w.is_finite() || !h.is_finite() || w <= 0.0 || h <= 0.0 || w > 32767.0 || h > 32767.0 {
    return Err(anyhow!("svg extents {w}x{h} unsupported"));
}

Type guard

fn valid_extents(bounds: &kurbo::Rect) -> bool {
    let (w, h) = (bounds.width(), bounds.height());
    w.is_finite() && h.is_finite() && w > 0.0 && h > 0.0 && w <= 32767.0 && h <= 32767.0
}

Try / catch

match svg::gen_with_cairo(bounds, draw) {
    Ok(svg) => svg,
    Err(e) if e.to_string().contains("Creating svg surface") => {
        eprintln!("export area too large or invalid: {e}");
        svg::gen_with_cairo(bounds.shrink_to_limit(), draw)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling gen_with_cairo with bounds whose extents are zero, negative, non-finite, or exceed cairo's surface size limits (roughly >2^15-2^16 px depending on backend/version).

Common situations: Exporting a very large or zoomed canvas producing extents beyond cairo limits; NaN/infinite extents from degenerate geometry slipping past validation; exotic cairo builds on headless systems.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of flxzt/rnote@bbc5354502 (2026-09-08). Data as JSON: /api/errors/a587ccfe3cc66dec. Report an issue: GitHub.

Appendix: source

Thrown at crates/rnote-engine/src/svg.rs:117

        self.svg_data = usvg_tree.to_string(&xml_options);
        self.bounds = bounds_simplified;

        Ok(())
    }

    /// Generate an Svg through cairo's SvgSurface.
    pub fn gen_with_cairo<F>(draw_func: F, mut bounds: Aabb) -> anyhow::Result<Self>
    where
        F: FnOnce(&cairo::Context) -> anyhow::Result<()>,
    {
        bounds.ensure_positive();
        bounds.assert_valid()?;

        let width = bounds.extents()[0];
        let height = bounds.extents()[1];
        let mut svg_surface =
            cairo::SvgSurface::for_stream(width, height, Vec::new()).map_err(|e| {
                anyhow::anyhow!(
                    "Creating svg surface with dimensions ({width}, {height}) failed, Err: {e:?}"
                )
            })?;
        svg_surface.set_document_unit(cairo::SvgUnit::Px);

        {
            let cairo_cx = cairo::Context::new(&svg_surface)?;
            // cairo only draws elements with positive coordinates, so we need to translate the content here
            cairo_cx.translate(-bounds.mins[0], -bounds.mins[1]);
            // apply the draw function
            draw_func(&cairo_cx)?;
        }

        let content = String::from_utf8(
            *svg_surface
                .finish_output_stream()
                .map_err(|e| {
                    anyhow::anyhow!("Finishing Svg surface output stream failed, Err: {e:?}")

View on GitHub (pinned to bbc5354502)