fix(sdk): fetchStateHistory should not crash if thread is empty (#1397)

This commit is contained in:
David Duong
2025-07-15 01:50:01 +02:00
committed by GitHub
parent 39cc88f308
commit c1ddda1c9b
4 changed files with 30 additions and 11 deletions
+7
View File
@@ -0,0 +1,7 @@
---
"@langchain/langgraph-api": patch
"@langchain/langgraph-cli": patch
"@langchain/langgraph-ui": patch
---
Embed methods for obtaining state should use `getGraph(...)`
+5
View File
@@ -0,0 +1,5 @@
---
"@langchain/langgraph-sdk": patch
---
Fix fetching state with `fetchStateHistory: false` causing crash if thread is empty
@@ -156,7 +156,7 @@ export function createEmbedServer(options: {
const thread = await options.threads.get(thread_id);
const graphId = thread.metadata?.graph_id as string | undefined | null;
const graph = graphId ? options.graph[graphId] : undefined;
const graph = graphId ? await getGraph(graphId) : undefined;
if (graph == null) {
return jsonExtra(
@@ -190,7 +190,7 @@ export function createEmbedServer(options: {
const thread = await options.threads.get(thread_id);
const graphId = thread.metadata?.graph_id as string | undefined | null;
const graph = graphId ? options.graph[graphId] : undefined;
const graph = graphId ? await getGraph(graphId) : undefined;
if (graph == null) return jsonExtra(c, []);
const config = { configurable: { thread_id, ...checkpoint } };
+16 -9
View File
@@ -244,7 +244,8 @@ function getBranchSequence<StateType extends Record<string, unknown>>(
}
for (const value of children) {
const id = value.checkpoint.checkpoint_id!;
const id = value.checkpoint?.checkpoint_id;
if (id == null) continue;
let { sequence } = task;
let { path } = task;
@@ -297,7 +298,10 @@ function getBranchView<StateType extends Record<string, unknown>>(
if (item.type === "node") {
history.push(item.value);
branchByCheckpoint[item.value.checkpoint.checkpoint_id!] = {
const checkpointId = item.value.checkpoint?.checkpoint_id;
if (checkpointId == null) continue;
branchByCheckpoint[checkpointId] = {
branch: item.path.join(PATH_SEP),
branchOptions: (item.path.length > 0
? pathMap[item.path.at(-2) ?? ROOT_ID] ?? []
@@ -312,7 +316,7 @@ function getBranchView<StateType extends Record<string, unknown>>(
? item.items.findIndex((value) => {
const firstItem = value.items.at(0);
if (!firstItem || firstItem.type !== "node") return false;
return firstItem.value.checkpoint.checkpoint_id === forkId;
return firstItem.value.checkpoint?.checkpoint_id === forkId;
})
: -1;
@@ -330,9 +334,10 @@ function fetchHistory<StateType extends Record<string, unknown>>(
options?: { limit?: boolean | number }
) {
if (options?.limit === false) {
return client.threads
.getState<StateType>(threadId)
.then((state) => [state]);
return client.threads.getState<StateType>(threadId).then((state) => {
if (state.checkpoint == null) return [];
return [state];
});
}
const limit = typeof options?.limit === "number" ? options.limit : 1000;
@@ -961,9 +966,11 @@ export function useStream<
| ThreadState<StateType>
| undefined;
let branch = firstSeen
? branchByCheckpoint[firstSeen.checkpoint.checkpoint_id!]
: undefined;
const checkpointId = firstSeen?.checkpoint?.checkpoint_id;
let branch =
firstSeen && checkpointId != null
? branchByCheckpoint[checkpointId]
: undefined;
if (!branch?.branch?.length) branch = undefined;