Skip to content

Calling withStructuredOutput with schema modifies schema and removes transform() configurations #9100

@ro0sterjam

Description

@ro0sterjam

Checked other resources

  • This is a bug, not a usage question. For questions, please use the LangChain Forum (https://forum.langchain.com/).
  • I added a very descriptive title to this issue.
  • I searched the LangChain.js documentation with the integrated search.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain.js rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).

Example Code

import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod/v4";

const schema = z.object({
  message: z.string().transform((x) => x.toUpperCase()),
});

const schemaUntouched = z.object({
  message: z.string().transform((x) => x.toUpperCase()),
});

const chatbot = new ChatOpenAI({ temperature: 0 });

const messages = ["Hello"];
const prompt = await ChatPromptTemplate.fromMessages(messages);

console.log(JSON.stringify(schema) === JSON.stringify(schemaUntouched)); // logs true

const chatbotWithStructuredOutput = chatbot.withStructuredOutput(schema, {
  includeRaw: true,
});

console.log(JSON.stringify(schema) === JSON.stringify(schemaUntouched)); // logs false

const runnable = prompt.pipe(chatbotWithStructuredOutput);
const result = await runnable.invoke({});

console.log(schema.parse(result.parsed)); // Logs { message: 'Hello' }
console.log(schemaUntouched.parse(result.parsed)); // Logs { message: 'HELLO' }

Error Message and Stack Trace (if applicable)

No response

Description

When I pass a schema to withStructuredOutput, it appears to modify the schema itself, in my particular case it is removing any transform() methods I have configured on the schema.

The example demonstrates that calling parse from the passed in schema does not perform the transform, but calling parsed on the untouched copy of the schema does.

Additionally you can see via the logs before and after calling withStructuredOutput that the schema is in fact mutated.

System Info

Langchain 0.3.35
Node v24.5.0
OSX 15.6.1 (24G90)

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions