Skip to content

Commit 1787f9d

Browse files
committed
fix(memory): split 431 embedding batches
1 parent 1c65500 commit 1787f9d

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

extensions/memory-core/src/memory/manager-embedding-policy.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,32 @@ describe("memory embedding policy", () => {
126126
expect(isRetryableMemoryEmbeddingTransportError("embedding validation failed")).toBe(false);
127127
});
128128

129+
it("splits OpenAI 431 oversized embedding batches without retrying the same request", async () => {
130+
const run = vi.fn(async (items: string[]) => {
131+
if (items.length > 1) {
132+
throw new Error(
133+
"openai embeddings failed: 431 request_headers_too_large: Request Header Fields Too Large",
134+
);
135+
}
136+
return items.map((item) => [item.charCodeAt(0)]);
137+
});
138+
139+
const result = await runMemoryEmbeddingBatchRetryWithSplit({
140+
items: ["a", "b", "c", "d"],
141+
run,
142+
isRetryable: isRetryableMemoryEmbeddingError,
143+
isSplittable: isSplittableMemoryEmbeddingTransportError,
144+
waitForRetry: async () => {},
145+
maxAttempts: 3,
146+
baseDelayMs: 500,
147+
});
148+
149+
expect(result).toEqual([[97], [98], [99], [100]]);
150+
expect(run.mock.calls.map(([items]) => items.length)).toEqual([4, 2, 1, 1, 2, 1, 1]);
151+
expect(isRetryableMemoryEmbeddingError("431 request_headers_too_large")).toBe(false);
152+
expect(isSplittableMemoryEmbeddingTransportError("431 request_headers_too_large")).toBe(true);
153+
});
154+
129155
it("retries too-many-tokens-per-day errors", async () => {
130156
let calls = 0;
131157
const waits: number[] = [];

extensions/memory-core/src/memory/manager-embedding-policy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const RETRYABLE_MEMORY_EMBEDDING_TRANSPORT_ERROR_RE =
8888
/(fetch failed|other side closed|ECONNRESET|ECONNREFUSED|ETIMEDOUT|EPIPE|UND_ERR_|socket hang up|socket terminated|network error|read ECONN|timed out|connection (?:reset|refused|aborted|timed out)|EHOSTUNREACH|ENETUNREACH|ECONNABORTED|EAI_AGAIN)/i;
8989

9090
const SPLITTABLE_MEMORY_EMBEDDING_TRANSPORT_ERROR_RE =
91-
/(other side closed|ECONNRESET|EPIPE|UND_ERR_SOCKET|socket hang up|socket terminated|read ECONN|connection (?:reset|aborted))/i;
91+
/(431|request_headers_too_large|request header fields too large|other side closed|ECONNRESET|EPIPE|UND_ERR_SOCKET|socket hang up|socket terminated|read ECONN|connection (?:reset|aborted))/i;
9292

9393
export function isRetryableMemoryEmbeddingTransportError(message: string): boolean {
9494
return RETRYABLE_MEMORY_EMBEDDING_TRANSPORT_ERROR_RE.test(message);

0 commit comments

Comments
 (0)