AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

With_fallbacks(Exception_key=...) Writes The Exception Into The Caller'S Own Input Mapping

The RunnableWithFallbacks methods mutate the caller-provided input dictionary by inserting the exception_key, violating expected immutability and causing unexpected side effects across all six entry points (invoke, ainvoke, batch, abatch, stream, astream).

highConfidence 92%Langchain-CoreAffected V1.6.5

Origin Analysis

In langchain_core/runnables/fallbacks.py, each fallback invocation directly assigns `input[self.exception_key] = last_error` on the original input object instead of creating a copy. This mutates the caller's dict because Python dicts are passed by reference.
1. Create a RunnableLambda that always raises ValueError. 2. Attach a fallback using `with_fallbacks(..., exception_key='error')`. 3. Pass a fresh dict `{'a': 1}` to `invoke`, `ainvoke`, `batch`, `abatch`, `stream`, or `astream`. 4. After the call, inspect the original dict; it now contains the extra key `'error'` with the exception object.

Fixing Code Block

Edge Case Audit

The fix assumes `input` is a dict; if a non-dict input is passed while `exception_key` is set, the copy operation will raise a TypeError (same as the previous code, but without side effects). If upstream code later relies on the mutated original dict, this change would break that hidden contract, but such reliance is unlikely and considered a bug. To rollback, revert the six lines to the original in-place assignment. For extra safety, wrap the copy with `if isinstance(input, dict):` to gracefully handle non-dict inputs.

Ecosystem Topology