Skip to content

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

@Void-Creator-Deity

Description

@Void-Creator-Deity

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions