Issue: 422 Error with RunnablePassthrough/RunnableParallel in LangServe, Works Fine Locally #256

Open
opened 2026-02-16 00:19:50 -05:00 by yindo · 0 comments
Owner

Originally created by @Void-Creator-Deity on GitHub (Nov 16, 2025).

Problem Description

I'm building a backend using LangServe and FastAPI. My API endpoint encounters a 422 error when using RunnablePassthrough() or RunnableParallel, but works when I add RunnableLambda at the beginning. All versions work

perfectly in local testing.

Detailed Issue

Chains that fail in LangServe (422 error):

#python
# Failing Option 1 - RunnablePassthrough
chain = (
    RunnablePassthrough()
    .assign(
        context=lambda x: retriever.invoke(x["question"]),
        question=lambda x: x["question"] 
    )
    | prompt
    | llm
    | StrOutputParser()
)


# Failing Option 2 - RunnableParallel  
chain = (
    RunnableParallel({
        "context": lambda x: retriever.invoke(x["question"]),
        "question": lambda x: x["question"]
    })
    | prompt
    | llm
    | StrOutputParser()
)

Working solution with RunnableLambda:

#python
def debug_input(x):
    print(f"[QA Chain] Actual input received: {x}, type: {type(x)}")
    return x

chain = (
    RunnableLambda(debug_input)
    .assign(
        context=lambda x: retriever.invoke(x["question"]),
        question=lambda x: x["question"]
    )
    | prompt
    | llm
    | StrOutputParser()
)

Important Additional Information

Local testing works fine:
When I test the same chain locally in the API's main Python file, all versions work correctly:

#python
if __name__ == "__main__":
    # Test pipeline
    qa_chain = load_qa_chain()
    test_question = "What are the core functions of the void system?"
    result = qa_chain.invoke({"question": test_question})
    print(f"Q: {test_question}\nA: {result}")

Key Observations

All versions work perfectly in local testing
The issue only occurs when exposing the chain through LangServe/FastAPI
(I'm using standard LangServe registration without any custom unpacking logic)

After examining the source code, I found that RunnableLambda has more flexible input acceptance

Both RunnablePassthrough and RunnableParallel also accept Any input but appear to have stricter validation in the LangServe environment

Questions I'd Like to Understand

Why do RunnablePassthrough and RunnableParallel fail with 422 errors in LangServe while working perfectly in local testing?

Why does adding RunnableLambda resolve this issue?

Is there a fundamental difference in how these components handle input validation in LangServe vs local execution?

What would be the proper way to use RunnablePassthrough and RunnableParallel in LangServe without the workaround?

Additional Context

I'm a university student working on this project and encountered this issue over the past couple of days. I've tried analyzing the source code with AI assistance but still can't figure out the root cause. If this turns out to be a simple or obvious issue, I apologize in advance and would appreciate your guidance.

Thank you for any insights into this behavior!

Originally created by @Void-Creator-Deity on GitHub (Nov 16, 2025). ### Problem Description I'm building a backend using LangServe and FastAPI. My API endpoint encounters a 422 error when using RunnablePassthrough() or RunnableParallel, but works when I add RunnableLambda at the beginning. All versions work perfectly in local testing. ### Detailed Issue Chains that fail in LangServe (422 error): ``` #python # Failing Option 1 - RunnablePassthrough chain = ( RunnablePassthrough() .assign( context=lambda x: retriever.invoke(x["question"]), question=lambda x: x["question"] ) | prompt | llm | StrOutputParser() ) # Failing Option 2 - RunnableParallel chain = ( RunnableParallel({ "context": lambda x: retriever.invoke(x["question"]), "question": lambda x: x["question"] }) | prompt | llm | StrOutputParser() ) ``` ### Working solution with RunnableLambda: ``` #python def debug_input(x): print(f"[QA Chain] Actual input received: {x}, type: {type(x)}") return x chain = ( RunnableLambda(debug_input) .assign( context=lambda x: retriever.invoke(x["question"]), question=lambda x: x["question"] ) | prompt | llm | StrOutputParser() ) ``` ### Important Additional Information Local testing works fine: When I test the same chain locally in the API's main Python file, all versions work correctly: ``` #python if __name__ == "__main__": # Test pipeline qa_chain = load_qa_chain() test_question = "What are the core functions of the void system?" result = qa_chain.invoke({"question": test_question}) print(f"Q: {test_question}\nA: {result}") ``` ### Key Observations **All versions work perfectly in local testing** **The issue only occurs when exposing the chain through LangServe/FastAPI** (I'm using standard LangServe registration without any custom unpacking logic) After examining the source code, I found that RunnableLambda has more flexible input acceptance Both RunnablePassthrough and RunnableParallel also accept Any input but appear to have stricter validation in the LangServe environment ### Questions I'd Like to Understand Why do RunnablePassthrough and RunnableParallel fail with 422 errors in LangServe while working perfectly in local testing? Why does adding RunnableLambda resolve this issue? Is there a fundamental difference in how these components handle input validation in LangServe vs local execution? What would be the proper way to use RunnablePassthrough and RunnableParallel in LangServe without the workaround? ### Additional Context I'm a university student working on this project and encountered this issue over the past couple of days. I've tried analyzing the source code with AI assistance but still can't figure out the root cause. If this turns out to be a simple or obvious issue, I apologize in advance and would appreciate your guidance. Thank you for any insights into this behavior!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langserve#256