`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_Source: langchain-ai/langchain