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
{{ message }}
Repository navigation
[Bug] OpenAI embedder skips the max_input_tokens truncation guard for plain list[str] inputs — oversized directory-meta overviews reach the provider (embedding 1210) #5760
OpenAICompatibleEmbedder._prepare_embedding_input() bypasses the max_input_tokens truncation guard entirely when the input is a plain list[str]. The directory-overview vectorization path (vectorize_directory_meta) submits its text as a plain string list, so long .overview.md bodies reach the provider untruncated and get rejected with 400 {'code': '1210'} (bigmodel embedding-3).
A memory-type directory whose .overview.md is large (ours: memories/trajectories/.overview.md at 9.4 KB, listing every trajectory file).
Any write under that directory triggers MemoryUpdater.generate_overview → vectorize_directory_meta(uri, abstract, overview, ...) (utils/embedding_utils.py).
The overview text is embedded as a plain list[str]; _prepare_embedding_input (models/embedder/openai_embedders.py:322-325) returns it untruncated:
Observed in production: every session commit touching memories/trajectories/ failed its embedding step until the overview was bounded.
Why the per-file path does not hit this
The single-string file path truncates correctly via truncate_embedding_input(content, embedding_cfg.max_input_tokens) (embedding_utils.py:669/702). Only the plain-list branch lacks the guard.
Suggested fix
Apply the same truncation to plain string lists, mirroring prepare_embedding_input:
While diagnosing, we measured estimate_embedding_input_tokens against bigmodel embedding-3 usage.total_tokens:
Sample
chars
CJK
actual tokens
estimate (cjk + other/4)
actual/estimate
CJK-dense (events content)
1570
1570
966
1570
0.62×
English-dense (SKILL.md)
4000
0
1148
1000
1.15×
Mixed (zh 3000 + en 2000)
5000
1660
2494
2495
1.00×
The formula is well-calibrated for mixed CJK+Latin content (the dominant memory case); English-only text is under-counted ~15% (other/4 → measured ≈ other/3.5). Pure-CJK is over-counted (harmless direction). Optionally worth revisiting the Latin coefficient.
Impact
Any deployment using a directory-overview-producing memory type with an embedding provider that enforces an input token limit (bigmodel embedding-3 confirmed) fails embedding for that directory on every write until the overview is manually bounded.
Root cause: a plain list[str] batch skips the truncation guard entirely — the OpenAI lower guard passes it through verbatim while the base guard either collapses it to "" (text-only embedders) or appends untruncated items (multimodal), so the two layers contradict each other on a contractually allowed input shape.
Plan: add a plain-list branch to the base guard with per-item truncation and align the lower guard to bound each item as well — no changes to truncate_embedding_input, token estimation, or EmbeddingMsg validation. Working on a fix now.
Activity
akushonkamen commentedon Oct 8, 2026
Root cause: a plain
list[str]batch skips the truncation guard entirely — the OpenAI lower guard passes it through verbatim while the base guard either collapses it to""(text-only embedders) or appends untruncated items (multimodal), so the two layers contradict each other on a contractually allowed input shape.Plan: add a plain-list branch to the base guard with per-item truncation and align the lower guard to bound each item as well — no changes to
truncate_embedding_input, token estimation, orEmbeddingMsgvalidation. Working on a fix now.akushonkamen commentedon Oct 8, 2026
Opened #5771 with the two-layer per-item truncation fix.
fix(embedding): truncate plain list inputs to max_input_tokens (#5760) (