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
AI Assistant: mid-run observation compaction (#37234) sends two system messages, breaking strict OpenAI-compatible backends (System message must be at the beginning) #37589
Since 2.38.1 (contains #37234 "Trigger observational memory mid-run on a token budget"), long AI Assistant runs fail deterministically right after the first mid-run compaction, with:
APICallError: could not encode request: System message must be at the beginning.
UI shows "Something went wrong before I could finish that response" / "No output generated. Check the stream for errors."
Root cause: when the observation log becomes non-empty, buildSystemMessages() in packages/@n8n/agents/src/runtime/model/message-list.ts returns two system entries
(base instructions + volatile sections incl. observation log). The OpenAI Chat Completions
spec tolerates multiple system messages, and OpenAI/Anthropic/OpenRouter accept them —
but many open-weights chat templates reject any system message that is not the single
first message, including Qwen-family ChatML templates served by vLLM
(the could not encode request: prefix wraps the Jinja raise_exception).
This makes the compaction feature unusable on a large class of self-hosted models,
even though the compaction itself completes successfully.
To Reproduce
n8n 2.38.1 (docker), AI Assistant with a custom OpenAI-compatible base URL pointing at vLLM serving a Qwen-family model (e.g. Qwen3 chat template).
Start an AI Assistant conversation long enough to trigger mid-run observational-memory compaction (logs: Observational memory task queued/started/completed).
The very next main-loop streamText call sends system: [base, observation-log] → HTTP 400 → run dies.
Minimal probe against the model server (no n8n needed):
request
result
[{system},{user}]
200
[{system},{system},{user}] (two consecutive leading systems)
400System message must be at the beginning.
system after an assistant turn
400 same
Expected behavior
Compaction continues the run; the request shape stays compatible with strict OpenAI-compatible servers.
Proposed fix
Concatenate the base instructions and volatile sections into a single system message (they are already joined with \n\n semantics). A single leading system message is the lowest-common-denominator shape every OpenAI-compatible server accepts. Alternatively, put the observation log into the unmasked user-role continuation message, or expose a setting.
Workarounds currently used
A small sidecar proxy that merges all system messages into one leading system message before forwarding to vLLM.
N8N_INSTANCE_AI_OBSERVER_MESSAGE_TOKENS=10000 (default 30000): because fix(core): Gate observation on the model-facing window budget (no-changelog) #37438 makes estimateVisibleBudget under-count large tool results ([omitted large blob]), lowering the threshold lets the (under-)estimated budget cross the soft threshold early enough that mid-run compaction fires before a ~131K local window overflows.
Environment
OS: macOS (Docker Desktop)
n8n version: 2.38.1 (pre-release)
Database: SQLite
AI backend: self-hosted vLLM (uvicorn), OpenAI-compatible custom base URL
Bug description
Since 2.38.1 (contains #37234 "Trigger observational memory mid-run on a token budget"), long AI Assistant runs fail deterministically right after the first mid-run compaction, with:
UI shows "Something went wrong before I could finish that response" / "No output generated. Check the stream for errors."
Root cause: when the observation log becomes non-empty,
buildSystemMessages()inpackages/@n8n/agents/src/runtime/model/message-list.tsreturns two system entries(base instructions + volatile sections incl. observation log). The OpenAI Chat Completions
spec tolerates multiple system messages, and OpenAI/Anthropic/OpenRouter accept them —
but many open-weights chat templates reject any system message that is not the single
first message, including Qwen-family ChatML templates served by vLLM
(the
could not encode request:prefix wraps the Jinjaraise_exception).This makes the compaction feature unusable on a large class of self-hosted models,
even though the compaction itself completes successfully.
To Reproduce
Observational memory task queued/started/completed).streamTextcall sendssystem: [base, observation-log]→ HTTP 400 → run dies.Minimal probe against the model server (no n8n needed):
[{system},{user}][{system},{system},{user}](two consecutive leading systems)System message must be at the beginning.Expected behavior
Compaction continues the run; the request shape stays compatible with strict OpenAI-compatible servers.
Proposed fix
Concatenate the base instructions and volatile sections into a single system message (they are already joined with
\n\nsemantics). A single leading system message is the lowest-common-denominator shape every OpenAI-compatible server accepts. Alternatively, put the observation log into the unmasked user-role continuation message, or expose a setting.Workarounds currently used
N8N_INSTANCE_AI_OBSERVER_MESSAGE_TOKENS=10000(default 30000): because fix(core): Gate observation on the model-facing window budget (no-changelog) #37438 makesestimateVisibleBudgetunder-count large tool results ([omitted large blob]), lowering the threshold lets the (under-)estimated budget cross the soft threshold early enough that mid-run compaction fires before a ~131K local window overflows.Environment
Related
context_length_exceeded(no compression available before 2.38)