#40341·langchain

`HTMLHeaderTextSplitter` raises `ValueError` on init for the non-heading tags its splitter already supports

Author: subhashpolisettiCreated Sep 9, 2026Updated Sep 17, 2026
Labelsbugtext-splittersexternal
### Submission checklist - [x] This is a bug, not a usage question. - [x] I added a clear and descriptive title that summarizes this issue. - [x] I used the GitHub search to find a similar question and didn't find it. - [x] I am sure that this is a bug in LangChain rather than my code. - [x] The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package). - [x] This is not related to the langchain-community package. - [x] I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS. ### Package (Required) - [ ] langchain - [ ] langchain-openai - [ ] langchain-anthropic - [ ] langchain-classic - [ ] langchain-core - [ ] langchain-model-profiles - [ ] langchain-tests - [x] langchain-text-splitters - [ ] langchain-chroma - [ ] langchain-deepseek - [ ] langchain-exa - [ ] langchain-fireworks - [ ] langchain-groq - [ ] langchain-huggingface - [ ] langchain-mistralai - [ ] langchain-nomic - [ ] langchain-ollama - [ ] langchain-openrouter - [ ] langchain-perplexity - [ ] langchain-qdrant - [ ] langchain-xai - [ ] Other / not sure / general ### Related Issues / PRs #40279 and #40298 are recent `text-splitters` reports, but neither touches header-tag handling. Nothing existing covers `headers_to_split_on` rejecting a tag outside `h1` to `h6`. ### Reproduction Steps / Example Code (Python) ```python from langchain_text_splitters import HTMLHeaderTextSplitter # `div` is one of the tags the splitting engine already assigns a fallback level to. HTMLHeaderTextSplitter(headers_to_split_on=[("h1", "Header 1"), ("div", "Div")]) ``` ### Error Message and Stack Trace (if applicable) ```shell Traceback (most recent call last): File "repro.py", line 4, in HTMLHeaderTextSplitter(headers_to_split_on=[("h1", "Header 1"), ("div", "Div")]) File ".../langchain_text_splitters/html.py", line 175, in __init__ self.headers_to_split_on = sorted( ^^^^^^^ File ".../langchain_text_splitters/html.py", line 176, in headers_to_split_on, key=lambda x: int(x[0][1:]) ^^^^^^^^^^^^^ ValueError: invalid literal for int() with base 10: 'iv' ``` ### Description **What I expect.** `HTMLHeaderTextSplitter` documents `headers_to_split_on` as "a list of `(header_tag, header_name)` pairs representing the headers that define splitting boundaries", with no restriction to `h1` through `h6`. Its splitting engine goes further and handles other tags deliberately, so constructing the splitter with one should work. **What happens.** The constructor raises `ValueError: invalid literal for int() with base 10` for any tag outside `h1` to `h6`. The splitter cannot be built, so none of the splitting code ever runs. **Why this is a bug rather than an unsupported input.** The same class disagrees with itself. `_generate_documents` (`html.py` ~line 328) assigns non-numeric tags a fallback level on purpose: ```python # Determine numeric level (h1->1, h2->2, etc.) try: level = int(tag[1:]) except ValueError: level = 9999 ``` That fallback is reachable and does real work: a `div` carrying text nests under an active `h1` rather than replacing it, and a later `h1` closes it again, which is exactly what level 9999 is for. But `__init__` (~line 175) sorts the same list with a bare conversion and no fallback: ```python self.headers_to_split_on = sorted( headers_to_split_on, key=lambda x: int(x[0][1:]) ) ``` So the engine supports these tags and the constructor rejects them. The sibling `HTMLSectionSplitter` in the same module shows what a deliberate restriction looks like: its docstring states "Allowed header values: `h1`, `h2`, `h3`, `h4`, `h5`, `h6`" and it does not sort at all. `HTMLHeaderTextSplitter` documents no such limit and implements the fallback instead. **Scope.** Only `HTMLHeaderTextSplitter.__init__`. `HTMLSectionSplitter` does not sort and is unaffected. Splitting on `h1` to `h6` is unchanged, since a numeric tag takes the same path either way. **Impact.** Any caller wanting to split on a semantic or container tag hits the crash at construction. It is not recoverable by argument order or by the `return_each_element` flag, and the error names an implementation detail (`'iv'`, the tag minus its first character) rather than the tag that was rejected, so the cause is not obvious from the message. Worth noting for scope: a container element that wraps its text in child elements, such as `

..

..

`, has no direct text of its own, and the engine only treats a node as a header when it has direct text. Fixing the constructor does not change that, and I am not proposing to. The tags this makes usable are the ones that carry text directly, which is the case the fallback level was written for. **Expected.** The constructor should use the same level lookup the engine already uses, so a tag outside `h1` to `h6` sorts below every numbered heading instead of raising. That is one shared helper rather than two copies of the conversion. I have the change plus three unit tests locally; all three fail without it. Happy to open a PR. ### System Info System Information ------------------ > OS: Darwin > OS Version: Darwin Kernel Version 25.6.0: Fri Jul 31 19:17:26 PDT 2026; root:xnu-12377.161.14~5/RELEASE_ARM64_T6041 > Python Version: 3.12.13 (main, Jul 18 2026, 16:55:18) [Clang 22.1.3 ] Package Information ------------------- > langchain_core: 1.6.2 > langchain_text_splitters: 1.1.2 > langsmith: 0.11.1 > langchain_tests: 1.1.9 Reproduced on master at 1611938f49. ### Social handles (optional) _No response_