flxzt/rnote · error

no page at index

Error message

no page at index '{page_i}

What it means

Importing a PDF into an Image by rendering its pages to PNG. from_pdf_bytes takes a page range and looks each page up in the parsed PDF's page list; if an index in that range is not present, this error is thrown. It means the requested page index is out of bounds for the loaded document.

Solutions

  1. Clamp the page range to pages.len() before calling from_pdf_bytes
  2. Convert 1-based UI page numbers to 0-based indices (subtract 1)
  3. Parse the PDF first (e.g. hayro_syntax::Pdf::new) and validate page count before requesting pages
  4. Return a user-facing 'page N does not exist' message with the actual page count

Example fix

// before
let pages = 0..10;
image::Image::from_pdf_bytes(bytes, pages, zoom, None)?;
// after
let page_count = hayro_syntax::Pdf::new(bytes.into())?.pages().len();
let pages = 0..10.min(page_count as u32);
image::Image::from_pdf_bytes(bytes, pages, zoom, None)?;
Defensive patterns

Strategy: validation

Validate before calling

let page_count = hayro_syntax::Pdf::new(bytes.clone().into())?.pages().len() as u32;
assert!(page_range.start < page_count && page_range.end <= page_count, "page range {page_range:?} exceeds {} pages", page_count);

Type guard

fn page_range_in_bounds(range: std::ops::Range<u32>, page_count: usize) -> bool {
    range.start < range.end && (range.end as usize) <= page_count
}

Try / catch

match from_pdf_bytes(bytes, range, zoom, password) {
    Ok(imgs) => imgs,
    Err(e) if e.to_string().contains("no page at index") => {
        eprintln!("requested pages not in document, clamping to available pages");
        from_pdf_bytes(bytes, clamp_range(range, actual_count), zoom, password)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling VectorImage::from_pdf_bytes (bitmapimage equivalent: Image::from_pdf_bytes with Pdf) with a page range like 0..10 on a PDF that has fewer pages, or using 1-based page numbers instead of 0-based indices.

Common situations: Users select 'pages 5-10' in an import dialog for a 4-page PDF; documents re-saved or truncated before import; off-by-one confusion between UI page numbers (1-based) and API indices (0-based).

Related errors


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

Appendix: source

Thrown at crates/rnote-engine/src/strokes/bitmapimage.rs:169

        } else {
            format.width() * (pdf_import_prefs.page_width_perc / 100.0)
        };

        // calculate the page zoom based on the width of the first page.
        let page_zoom = if let Some(first_page) = pages.first() {
            page_width / first_page.render_dimensions().0 as f64
        } else {
            return Ok(vec![]);
        };
        let x = insert_pos[0];
        let mut y = insert_pos[1];

        // TODO: investigate if this can be parallelized with rayon's `par_iter()`
        let pngs = page_range
            .map(|page_i| {
                let page = pages
                    .get(page_i)
                    .ok_or_else(|| anyhow::anyhow!("no page at index '{page_i}"))?;
                let (intrinsic_width, intrinsic_height) = {
                    let dimensions = page.render_dimensions();
                    (dimensions.0 as f64, dimensions.1 as f64)
                };
                let width = intrinsic_width * page_zoom;
                let height = intrinsic_height * page_zoom;
                let render_settings = hayro::RenderSettings {
                    x_scale: (pdf_import_prefs.bitmap_scalefactor * page_zoom) as f32,
                    y_scale: (pdf_import_prefs.bitmap_scalefactor * page_zoom) as f32,
                    width: Some((pdf_import_prefs.bitmap_scalefactor * width).ceil() as u16),
                    height: Some((pdf_import_prefs.bitmap_scalefactor * height).ceil() as u16),
                    bg_color: vello_cpu::color::AlphaColor::WHITE,
                };

                // TODO: implement drawing page borders.
                // Possibly with vello-cpu, since it already is a dependency of hayro
                let pixmap = hayro::render(page, &interpreter_settings, &render_settings);
                let png_data = pixmap.into_png()?;

View on GitHub (pinned to bbc5354502)