[PR #6438] fix(langgraph): allow providing both context and configurable in RemoteGraph, fixes #6342 #5036

Closed
opened 2026-02-20 17:51:07 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/langchain-ai/langgraph/pull/6438

State: closed
Merged: No


Description:

Fixes https://github.com/langchain-ai/langgraph/issues/6342

This PR fixes a 400 error in RemoteGraph when using both context and configurable together. It merges any configurable fields into context internally and removes the configurable key, allowing checkpointing and middleware to work under the context-first architecture introduced in LangGraph 1.0.

Summary of Issue

This PR resolves an issue where using both context and configurable together in RemoteGraph caused a 400 Bad Request error:

Cannot specify both configurable and context. Prefer setting context alone.
Context was introduced in LangGraph 0.6.0 and is the long term planned replacement for configurable.

The 400 error here isn’t about using both config and context, it’s specifically about using both configurable and context together. In other words, this line in the error:

Cannot specify both configurable and context.

refers to the configurable field inside config, not the entire config argument. You can safely pass both config and context as long as config doesn’t contain a configurable key.
So, instead of doing this:

config = {"configurable": {"thread_id": thread_id}}
context = {"user_id": "123"}

You can move those fields up into your context:

context = {"user_id": "123", "thread_id": thread_id}

and omit the configurable block entirely.

However, with this approach, checkpointing still doesn’t work, since the thread id being sent to the langgraph api comes from the config[”configurable”], not the context.


Fix Summary

  • Added an explicit context parameter to RemoteGraph.stream(), .astream(), .invoke(), and .ainvoke().
  • Unified configurable fields into context internally to prevent 400 errors from the API.
  • Ensures checkpointing continues to work when using context.
  • Aligns RemoteGraph API with LangGraph 1.0’s context-first architecture.

Correct Usage

Previously, this would fail because you can’t specify both configurable and context:

config = {"configurable": {"thread_id": "123"}}
context = {"user_id": "abc"}
remote_graph.ainvoke(input, config=config, context=context)

Now, you can simply do:

context = {"user_id": "abc", "thread_id": "123"}
config = {
    "run_name": "joke_generation",
    "tags": ["humor", "demo"],
} # remove configurable key from config

remote_graph.ainvoke(input, config=config, context=context)

Works because config does not contain a configurable key.

Everything that used to go inside configurable can now be placed directly in context.


Backward Compatibility

While it’s still technically possible to pass both configurable and context together, it’s not recommended. Internally, the configurable block is merged into context and removed to prevent API errors. This ensures existing workflows do not break while promoting the context-first model introduced in LangGraph 0.6.0.


Implementation Highlights

if context:
    context.update(sanitized_config["configurable"])
    sanitized_config.pop("configurable", None)

async for chunk in client.runs.stream(
    thread_id=context.get("thread_id")
    if context
    else sanitized_config["configurable"].get("thread_id"),
    assistant_id=self.assistant_id,
    input=input,
    command=command,
    config=sanitized_config,
    context=context,
    stream_mode=stream_modes,
    interrupt_before=interrupt_before,
    interrupt_after=interrupt_after,
    stream_subgraphs=subgraphs or stream is not None,
    if_not_exists="create",
    headers=(
        _merge_tracing_headers(headers) if self.distributed_tracing else headers
    ),
    params=params,
    **kwargs,
):
    ...
  • Merges configurable fields into context before sending the request.
  • Removes configurable from config to prevent API rejection.
  • Supports checkpointing and middleware under the unified context interface.

X handle - https://x.com/bolexyro

**Original Pull Request:** https://github.com/langchain-ai/langgraph/pull/6438 **State:** closed **Merged:** No --- ## **Description:** Fixes https://github.com/langchain-ai/langgraph/issues/6342 This PR fixes a 400 error in `RemoteGraph` when using both `context` and `configurable` together. It merges any `configurable` fields into `context` internally and removes the `configurable` key, allowing checkpointing and middleware to work under the context-first architecture introduced in LangGraph 1.0. ### Summary of Issue This PR resolves an issue where using both `context` and `configurable` together in `RemoteGraph` caused a `400 Bad Request` error: ```python Cannot specify both configurable and context. Prefer setting context alone. Context was introduced in LangGraph 0.6.0 and is the long term planned replacement for configurable. ``` The `400 error` here isn’t about using both config and context, it’s specifically about using both configurable and context together. In other words, this line in the error: ```python Cannot specify both configurable and context. ``` refers to the configurable field inside config, not the entire config argument. You can safely pass both config and context as long as config doesn’t contain a configurable key. So, instead of doing this: ```python config = {"configurable": {"thread_id": thread_id}} context = {"user_id": "123"} ``` You can move those fields up into your context: ```python context = {"user_id": "123", "thread_id": thread_id} ``` and omit the configurable block entirely. However, with this approach, checkpointing still doesn’t work, since the thread id being sent to the langgraph api comes from the config[”configurable”], not the context. --- ### **Fix Summary** - Added an explicit `context` parameter to `RemoteGraph.stream()`, `.astream()`, `.invoke()`, and `.ainvoke()`. - Unified `configurable` fields into `context` internally to prevent 400 errors from the API. - Ensures checkpointing continues to work when using `context`. - Aligns RemoteGraph API with LangGraph 1.0’s context-first architecture. --- ### **Correct Usage** Previously, this would fail because you can’t specify both configurable and context: ```python config = {"configurable": {"thread_id": "123"}} context = {"user_id": "abc"} remote_graph.ainvoke(input, config=config, context=context) ``` Now, you can simply do: ```python context = {"user_id": "abc", "thread_id": "123"} config = { "run_name": "joke_generation", "tags": ["humor", "demo"], } # remove configurable key from config remote_graph.ainvoke(input, config=config, context=context) ``` Works because `config` **does not contain a `configurable` key**. Everything that used to go inside `configurable` can now be placed directly in `context`. --- ### **Backward Compatibility** While it’s still technically possible to pass both `configurable` and `context` together, it’s **not recommended**. Internally, the `configurable` block is merged into `context` and removed to prevent API errors. This ensures existing workflows do not break while promoting the **context-first** model introduced in LangGraph 0.6.0. --- ### **Implementation Highlights** ```python if context: context.update(sanitized_config["configurable"]) sanitized_config.pop("configurable", None) async for chunk in client.runs.stream( thread_id=context.get("thread_id") if context else sanitized_config["configurable"].get("thread_id"), assistant_id=self.assistant_id, input=input, command=command, config=sanitized_config, context=context, stream_mode=stream_modes, interrupt_before=interrupt_before, interrupt_after=interrupt_after, stream_subgraphs=subgraphs or stream is not None, if_not_exists="create", headers=( _merge_tracing_headers(headers) if self.distributed_tracing else headers ), params=params, **kwargs, ): ... ``` - Merges `configurable` fields into `context` before sending the request. - Removes `configurable` from `config` to prevent API rejection. - Supports checkpointing and middleware under the unified context interface. X handle - https://x.com/bolexyro
yindo added the pull-request label 2026-02-20 17:51:07 -05:00
yindo closed this issue 2026-02-20 17:51:08 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#5036