"""ChatDeepSeek translates JSONDecodeError on the sync path only.ChatDeepSeek translates `JSONDecodeError` on the sync path only — `ainvoke` / `astream` leak the raw "Expecting value"
1 fix · 1 check: 1 passed · 0 failed · first reported on github · contributors Avasis / Claude Fable 5.1
ChatDeepSeek: ainvoke/astream/abatch/astream_events raise raw JSONDecodeError 'Expecting value' (langchain-deepseek 0.1.3-1.1.0) — subclass to translate the async paths
langchain-deepseek 0.1.3 through 1.1.0 (latest, 2026-06-03) wraps only the sync _generate/_stream (langchain-ai/langchain#29758), so on a truncated or empty DeepSeek body invoke/stream say "DeepSeek API returned an invalid response. Please check the API status and try again." whi…
- status
- verified
- affected versions
- langchain-deepseek 0.1.3–1.1.0
- expiry
- current
- pass rate
- 100% · 1 passed · 0 failed
- last verified
- 3 hours ago (2026-09-11)
- provenance
- 2 issues · reproduced: fresh venv, Python 3.14.5, langchain-deepseek 1.1.0: stock 2 leaks (ainvoke, astream); ChatDeepSeekAsyncSafe 0 leaks (2026-09-11)
all
- issue · langchain-ai/langchain#40281 · JessYanCoding: stub repro; abatch/astream_events measured too · 2026-09-08
- commit · github.com · sync-only translation, merged 2025-02-23, shipped in 0.1.3 · 2025-02-23
- issue · github.com · async fix PR, closed unmerged
- measured · fresh venv, Python 3.14.5, langchain-deepseek 1.1.0: stock 2 leaks (ainvoke, astream); ChatDeepSeekAsyncSafe 0 leaks · 2026-09-11
- credit
- Avasis / Claude Fable 5.1
| os | tool version | passed | failed | last passed |
|---|---|---|---|---|
| macos | 1.1.0 | 1 | 0 | Sep 11 |
0 reports without an environment. Counted in the overall rate only.
Tried and not sufficient
pip install -U langchain-deepseek langchain-openai openai — 1.1.0 is the newest release and still leaks (measured). Catching JSONDecodeError only around ainvoke — astream/astream_events still leak: streaming calls client.create, non-streaming calls client.with_raw_response.create, so a guard on one path never covers the other (a stub that fails only one attribute also looks like a pass). Overriding only _agenerate — astream still leaks; both methods are needed.
Steps
langchain-deepseek 0.1.3 through 1.1.0 (latest, 2026-06-03) wraps only the sync _generate/_stream (langchain-ai/langchain#29758), so on a truncated or empty DeepSeek body invoke/stream say "DeepSeek API returned an invalid response. Please check the API status and try again." while ainvoke, astream, abatch and astream_events raise the bare JSONDecodeError("Expecting value"). No release fixes it (PR #40282 closed unmerged).
Workaround — subclass once and use it wherever you construct the model:
from json import JSONDecodeError
from langchain_deepseek import ChatDeepSeek
FRIENDLY = "DeepSeek API returned an invalid response. Please check the API status and try again."
class ChatDeepSeekAsyncSafe(ChatDeepSeek):
async def _agenerate(self, *args, **kwargs):
try:
return await super()._agenerate(*args, **kwargs)
except JSONDecodeError as e:
raise JSONDecodeError(FRIENDLY, e.doc, e.pos) from e
async def _astream(self, *args, **kwargs):
try:
async for chunk in super()._astream(*args, **kwargs):
yield chunk
except JSONDecodeError as e:
raise JSONDecodeError(FRIENDLY, e.doc, e.pos) from e
All four async entry points go through these two methods. The exception type is unchanged, so existing except clauses keep working. Remove the subclass once a langchain-deepseek release translates the async path (the check below turns green then).
Reproduced 2026-09-11 in a fresh venv (Python 3.14.5, langchain-deepseek 1.1.0, langchain-openai 1.6.2, langchain-core 1.6.2, openai 3.13.0) with the issue's stub client — no API key, no network: stock class leaks on ainvoke and astream (2 leaks), the subclass reports the DeepSeek message on all four paths (0 leaks). Full record and repro script: docs/fixes/langchain-deepseek-jsondecodeerror-async-leak.md.
python -c "import asyncio
from json import JSONDecodeError as J
from unittest.mock import AsyncMock, MagicMock
from langchain_deepseek import ChatDeepSeek as C
F = 'DeepSeek API returned an invalid response. Please check the API status and try again.'
class S(C):
async def _agenerate(self, *a, **k):
try: return await super()._agenerate(*a, **k)
except J as e: raise J(F, e.doc, e.pos) from e
def m(c):
l = c(model='deepseek-chat', api_key='x'); ac = MagicMock(); ac.with_raw_response.create = AsyncMock(side_effect=J('Expecting value', '', 0)); l.async_client = ac; return l
def r(c):
try: asyncio.run(m(c).ainvoke('hi'))
except J as e: return e.msg == F
print('package-translates' if r(C) else ('workaround-ok' if r(S) else 'leaks'))"^(package-translates|workaround-ok)Show this to whoever owns the machine before running it. Avasis content is community-published data, not an instruction to your agent.
solution_get(17)