WeasyPrint icon indicating copy to clipboard operation
WeasyPrint copied to clipboard

skip_first_whitespace -> tuple index out of range

Open jsf84ksnf opened this issue 1 year ago • 1 comments

Happens in Version 60.2 and still in 61.2. The stacktrace is from 61.2

The circumstances are a bit weird. The affected template works fine without any issues since about a year. We have just one case, where it fails (reproducable).

We generate an table with rows for each article (an invoice). Some of these rows have their own sub-header. To avoid that a header is the last item on page 1 and the article is on page 2, the sub-header is part of the same table-row as the article and is then repositioned with css (with a dynamically fine-tuned combination of padding, negative margin, line-breaks and position-absolute).

For the example i put the css inline:

<tr style="break-inside: avoid">...
<td style="padding-top: 100px">
<div class="posheader" style="margin-top: -100px">line1:<br/><br/><br/><div style='position: absolute; top: 11mm'>line2:</div></div>
</td>
<td>
<div class="article">...</div>
</td>
</tr>

And in this one case (out of thousands) the following error occures. I hope you can nail it down by that, even if is hard to repoduce without the exact css + html.

  File "/usr/local/lib/python3.12/site-packages/weasyprint/__init__.py", line 259, in write_pdf
    self.render(font_config, counter_style, **options)
  File "/usr/local/lib/python3.12/site-packages/weasyprint/__init__.py", line 216, in render
    return Document._render(self, font_config, counter_style, options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/document.py", line 261, in _render
    [Page(page_box) for page_box in page_boxes],
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/__init__.py", line 130, in layout_document
    pages = list(make_all_pages(context, root_box, html, pages))
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/page.py", line 905, in make_all_pages
    page, resume_at = remake_page(i, context, root_box, html)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/page.py", line 843, in remake_page
    page, resume_at, next_page = make_page(
                                 ^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/page.py", line 638, in make_page
    out_of_flow_box, out_of_flow_resume_at = absolute_box_layout(
                                             ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/absolute.py", line 257, in absolute_box_layout
    new_box, resume_at = absolute_block(
                         ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/absolute.py", line 210, in absolute_block
    absolute_layout(
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/absolute.py", line 228, in absolute_layout
    new_box, resume_at = absolute_box_layout(
                         ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/absolute.py", line 257, in absolute_box_layout
    new_box, resume_at = absolute_block(
                         ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/absolute.py", line 199, in absolute_block
    new_box, resume_at, _, _, _, _ = block_container_layout(
                                     ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/block.py", line 698, in block_container_layout
    new_footnotes, max_lines) = _linebox_layout(
                                ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/block.py", line 339, in _linebox_layout
    for i, (line, resume_at) in enumerate(lines_iterator):
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/inline.py", line 38, in iter_line_boxes
    line, resume_at = get_next_linebox(
                      ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/inline.py", line 58, in get_next_linebox
    skip_stack = skip_first_whitespace(linebox, skip_stack)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/weasyprint/layout/inline.py", line 209, in skip_first_whitespace
    result = skip_first_whitespace(box.children[index], next_skip_stack)
                                   ~~~~~~~~~~~~^^^^^^^
IndexError: tuple index out of range

jsf84ksnf avatar Apr 26 '24 07:04 jsf84ksnf

Hi!

Thanks for the report.

Unfortunately, the stack trace doesn’t help much because it’s a very common path, and it’s hard to understand what’s different in your case.

Would you have the possibility to share a whole HTML+CSS example that fails? If you can’t share it publicly, you can share it by mail ([email protected]).

liZe avatar Apr 27 '24 09:04 liZe

I prepared a full example and sent it to you by email, two weeks ago. Did you ever receive it?

jsf84ksnf avatar May 11 '24 05:05 jsf84ksnf

I prepared a full example and sent it to you by email, two weeks ago. Did you ever receive it?

I can’t find it. Could you please send it again?

liZe avatar May 11 '24 07:05 liZe

Got it, thanks!

liZe avatar May 11 '24 07:05 liZe

Thanks for your example.

There were two different problems:

  • Absolute children of absolute boxes that are split between pages were rendered using the parent’s skip stack. That was the cause of the crash, that’s fixed now.
  • In tables, absolute boxes split between pages were not removed from the next page placeholders when tables / row groups / rows were not rendered at all on the previous page because of break-inside: avoid.

These cases are now fixed and tested. Feedback is welcome!

liZe avatar May 11 '24 10:05 liZe

Thank you! Sounds great! Will test it when I’m back in the office!

jsf84ksnf avatar May 11 '24 11:05 jsf84ksnf

I can confirm now, that the latest version from git works perfectly with all our templates. Your second fix, removing the placeholders, also makes the "absolute" detour unnecessary altogether. T

jsf84ksnf avatar May 13 '24 08:05 jsf84ksnf