You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have searched existing issues and this hasn't been mentioned before
I have read the project documentation and confirmed this issue doesn't already exist
This issue is specific to MemOS and not a general software issue
Bug Description | 问题描述
memos-local-plugin v2.0.10 feeding untruncated/un-chunked trace text to the embedding provider causes HTTP 400 errors. When using 智谱 embedding-3 (single-request cap 3072 tokens), any traces.summary or agent_text longer than ~6KB triggers code:1210 API 调用参数有误, and because the batch is aborted on the first failure (failed = batch.length), the entire batch — including short, valid entries — is marked failed. The "修复向量 / rebuild vectors" button in the Memory Viewer returns 400 immediately, and the periodic embedding heartbeat probe shows ~60% error rate.
Environment | 环境信息
Plugin: @memtensor/memos-local-pluginv2.0.10 (also confirmed in v2.0.6)
Embedding provider: openai_compatible → https://open.bigmodel.cn/api/paas/v4/embeddings, model embedding-3
智谱 embedding-3 official limits: 8K context window, 3072 tokens per single input, ≤64 inputs per batch (docs)
So ~40 traces exceed the 6KB (~3000 Chinese-char) mark. The longest summary and agent_text are 59,644 bytes each — roughly 30k Chinese characters, an order of magnitude over the 3072-token cap.
grep for chunk|truncat|slice|max.*token|token.*limit in embedder.ts returns only one hit — an unrelated .slice(0, 300) on tool-call inputs. The main text path is unguarded.
4. Blast radius: a single long entry nukes the whole batch
A 30k-char trace anywhere in the batch → 400 → the whole batch (every other short, valid trace included) is counted as failed. This is why the Memory Viewer's heartbeat shows ~94 errors out of 160 probes.
Impact
"Rebuild vectors" button is unusable when the DB contains any long trace — returns 400 within milliseconds.
Live capture silently degrades: embedSteps catches the same exception and writes null vectors for the entire step batch (see embedder.ts lines 53-58), so vector search becomes increasingly incomplete as long traces accumulate.
Heartbeat probe error rate ~60%, polluting the system-model-status log.
embedding_retry_queue accumulates: failed jobs keep retrying with the same oversized payload and never succeed.
Suggested Fixes
In rough order of effort:
Truncate source text before embedding (smallest change). Add a per-input character cap (e.g. 6000 chars ≈ 2700 tokens with safety margin) in embedder.embedMany or at the collectEmbeddingSlots boundary. Log a warning when truncation fires. This won't perfectly represent long traces but keeps retrieval working.
Chunked embedding for long inputs (best quality). When sourceText.length > cap, split into chunks of cap, embed each chunk separately, and average (or L2-normalize-pool) the vectors into a single embedding. The Embedder interface already returns a Float32Array, so the contract stays the same; the batch loop just needs to coalesce per-slot.
Don't abort the whole batch on one failure (orthogonal but important). Either (a) send inputs one-per-request when batch mode throws, or (b) split the batch in half on exception and retry each half — so a single oversized input only fails itself, not its neighbors.
Persist the provider's response body in http.non_ok warnings (also raised in LLM provider 400 errors from SiliconFlow + missing response body logging (memos-local-plugin) #1775, still relevant). Right now gateway.log shows embedding_unavailable: HTTP 400 from openai_compatible with no response body, which is why this bug took so long to pin down — the code:1210 message that points at the real cause is swallowed.
(1)+(3)+(4) together would resolve this end-to-end; (2) is the "correct" long-term fix.
How to Reproduce | 如何重现
Configure plugin with embedding provider = 智谱 embedding-3.
Insert (or naturally accumulate) any trace whose summary or agent_text exceeds ~6KB. The easiest way is a long multi-tool OpenClaw run — those routinely produce 30-60KB agent_text.
Open the Memory Viewer → Embedding Maintenance → click "修复向量 / Rebuild".
Observe: HTTP 400 returned within milliseconds, gateway.log shows [嵌入模型] · error · embedding_unavailable: HTTP 400 from openai_compatible with no body.
Pre-submission checklist | 提交前检查
Bug Description | 问题描述
memos-local-pluginv2.0.10 feeding untruncated/un-chunked trace text to the embedding provider causes HTTP 400 errors. When using 智谱embedding-3(single-request cap 3072 tokens), anytraces.summaryoragent_textlonger than ~6KB triggerscode:1210 API 调用参数有误, and because the batch is aborted on the first failure (failed = batch.length), the entire batch — including short, valid entries — is marked failed. The "修复向量 / rebuild vectors" button in the Memory Viewer returns 400 immediately, and the periodic embedding heartbeat probe shows ~60% error rate.Environment | 环境信息
@memtensor/memos-local-pluginv2.0.10 (also confirmed in v2.0.6)openai_compatible→https://open.bigmodel.cn/api/paas/v4/embeddings, modelembedding-3memos.db), 19,114 tracesEvidence
1. DB-side: source-text length distribution
So ~40 traces exceed the 6KB (~3000 Chinese-char) mark. The longest
summaryandagent_textare 59,644 bytes each — roughly 30k Chinese characters, an order of magnitude over the 3072-token cap.2. API-side: reproducing the 400
3. Code path: no truncation / no chunking anywhere
Three places feed source text straight into
embedManywith no length guard:core/pipeline/memory-core.ts:3998(insiderebuildEmbeddings— the "rebuild vectors" button):core/pipeline/memory-core.ts:4126(slot source forvec_summary):…and the
vec_actionslot is built fromtraceActionEmbeddingText(row), which includes the fullagent_text. Neither is truncated.core/capture/embedder.ts:93(live capture path):grepforchunk|truncat|slice|max.*token|token.*limitinembedder.tsreturns only one hit — an unrelated.slice(0, 300)on tool-call inputs. The main text path is unguarded.4. Blast radius: a single long entry nukes the whole batch
In
rebuildEmbeddings:A 30k-char trace anywhere in the batch → 400 → the whole batch (every other short, valid trace included) is counted as failed. This is why the Memory Viewer's heartbeat shows ~94 errors out of 160 probes.
Impact
embedStepscatches the same exception and writesnullvectors for the entire step batch (seeembedder.tslines 53-58), so vector search becomes increasingly incomplete as long traces accumulate.embedding_retry_queueaccumulates: failed jobs keep retrying with the same oversized payload and never succeed.Suggested Fixes
In rough order of effort:
Truncate source text before embedding (smallest change). Add a per-input character cap (e.g. 6000 chars ≈ 2700 tokens with safety margin) in
embedder.embedManyor at thecollectEmbeddingSlotsboundary. Log a warning when truncation fires. This won't perfectly represent long traces but keeps retrieval working.Chunked embedding for long inputs (best quality). When
sourceText.length > cap, split into chunks ofcap, embed each chunk separately, and average (or L2-normalize-pool) the vectors into a single embedding. TheEmbedderinterface already returns aFloat32Array, so the contract stays the same; the batch loop just needs to coalesce per-slot.Don't abort the whole batch on one failure (orthogonal but important). Either (a) send inputs one-per-request when batch mode throws, or (b) split the batch in half on exception and retry each half — so a single oversized input only fails itself, not its neighbors.
Persist the provider's response body in
http.non_okwarnings (also raised in LLM provider 400 errors from SiliconFlow + missing response body logging (memos-local-plugin) #1775, still relevant). Right nowgateway.logshowsembedding_unavailable: HTTP 400 from openai_compatiblewith no response body, which is why this bug took so long to pin down — thecode:1210message that points at the real cause is swallowed.(1)+(3)+(4) together would resolve this end-to-end; (2) is the "correct" long-term fix.
How to Reproduce | 如何重现
embedding-3.summaryoragent_textexceeds ~6KB. The easiest way is a long multi-tool OpenClaw run — those routinely produce 30-60KBagent_text.gateway.logshows[嵌入模型] · error · embedding_unavailable: HTTP 400 from openai_compatiblewith no body.Additional Context
Happy to open a PR for fix (1) + (3) + (4) if maintainers are open to it — I have the code paths mapped.