Bug type
Behavior bug (incorrect output/state without crash)
Summary
Open WebUI-backed chats that use an opaque bare UUID as the session key can split into two separate OpenClaw session records:
When that happens, one logical chat diverges between Open WebUI and OpenClaw Control UI.
Steps to reproduce
- Configure Open WebUI on top of OpenClaw so that a WebUI chat uses a stable bare UUID as its chat/session identity.
- Start a new chat in Open WebUI.
- Open the same chat in OpenClaw Control UI using that UUID.
- Send a message from Control UI.
- Inspect the session index and transcript files.
Short practical repro that we observed:
- Create a chat in Open WebUI.
- Open the same UUID in OpenClaw Control UI (
/chat?session=<uuid>).
- Send a message from Control UI.
- After that:
- history can diverge between the two UIs
- the original Open WebUI chat may no longer reflect the same thread
sessions.json can end up containing both <uuid> and agent:main:<uuid> as separate records
Expected behavior
For an Open WebUI-backed chat that already exists under a bare UUID, OpenClaw should preserve that UUID as the canonical session identity.
Control UI and Open WebUI should read/write the same session entity, and sessions.json should not create a second record under agent:main:<uuid>.
Actual behavior
One logical chat can become two separate OpenClaw session records:
This is not just an alias/display issue. In the broken case, the two entries have different:
That means the system is actually storing one logical chat as two backend sessions.
OpenClaw version
2026.3.13
Operating system
Ubuntu server
Install method
Self-hosted OpenClaw gateway with Open WebUI via Docker
Model
openai-codex/gpt-5.4
Provider / routing chain
Open WebUI -> local OpenAI-compatible proxy -> OpenClaw gateway -> openai-codex/gpt-5.4
Config file / key location
Relevant places:
~/.openclaw/agents/main/sessions/sessions.json
~/.openclaw/agents/main/sessions/<sessionId>.jsonl
src/gateway/session-utils.ts
src/gateway/server-methods/chat.ts
ui/src/ui/app-settings.ts
Additional provider/model setup details
Open WebUI was connected to OpenClaw through a local OpenAI-compatible proxy with stable chat/session IDs preserved across requests.
This does not appear to be a model/provider bug. It looks like a backend session canonicalization bug inside OpenClaw.
Logs, screenshots, and evidence
Key evidence: sessions.json contained two different records for the same logical chat:
And these were not two names for the same object. They pointed to different:
Example shape of the broken state:
- short key record:
sessionId: <id-a>
sessionFile: <id-a>.jsonl
- canonical key record:
sessionId: <id-b>
sessionFile: <id-b>.jsonl
That shows the problem had already crossed from "wrong key display" into actual duplicated session storage.
Additional clue: the UI already contains a special workaround in ui/src/ui/app-settings.ts:
normalizeChatUrlSessionKey(...)
- it rewrites
agent:main:<uuid> back to <uuid> for opaque UUID chats
That strongly suggests the frontend already knows these WebUI-backed UUID chats are special, while the backend still canonicalizes them too aggressively.
Impact and severity
Affected:
- self-hosted OpenClaw users who integrate Open WebUI and also access the same chats from OpenClaw Control UI
Severity:
Frequency:
- Reproducible for affected Open WebUI-backed chats
Consequence:
- one logical chat can split into two backend sessions
- history diverges between UIs
- some messages are written into a different transcript file
- already-broken chats require manual cleanup/repair
- operators cannot reliably use Open WebUI and Control UI as two views of the same conversation
Additional information
We traced the likely root cause and validated a local fix.
Root cause:
- in
src/gateway/session-utils.ts, a bare UUID such as <uuid> was treated like a generic session key and canonicalized into agent:main:<uuid>
- for Open WebUI-backed opaque UUID chats, that is incorrect because the bare UUID is already the real session identity
chat.send in src/gateway/server-methods/chat.ts then uses the canonicalized key, which allows Control UI writes to target a second backend entity instead of the original short-key session
Proposed fix
Apply a narrow backend fix:
- In
src/gateway/session-utils.ts, if the session key is a bare opaque UUID used by WebUI-backed chats, preserve it as-is.
- Do not rewrite
<uuid> into agent:main:<uuid> for that special case.
- Apply the same rule consistently to related session resolution / combined-store canonicalization paths.
- Keep this rule narrow and do not apply it to normal structured keys such as:
agent:main:telegram:...
agent:main:discord:...
- other standard agent session keys
Files involved in the fix
src/gateway/session-utils.ts
src/gateway/server-methods/chat.ts
- reference/hint from existing UI workaround:
ui/src/ui/app-settings.ts
Local verification
We validated a local fix that preserves bare UUID keys for WebUI-backed chats:
- new split sessions stopped being created
- bare UUIDs were no longer rewritten into
agent:main:<uuid> for these chats
- relevant gateway tests passed locally
Important note:
- this fix prevents new split cases
- it does not automatically merge already-broken historical session records
Bug type
Behavior bug (incorrect output/state without crash)
Summary
Open WebUI-backed chats that use an opaque bare UUID as the session key can split into two separate OpenClaw session records:
<uuid>agent:main:<uuid>When that happens, one logical chat diverges between Open WebUI and OpenClaw Control UI.
Steps to reproduce
Short practical repro that we observed:
/chat?session=<uuid>).sessions.jsoncan end up containing both<uuid>andagent:main:<uuid>as separate recordsExpected behavior
For an Open WebUI-backed chat that already exists under a bare UUID, OpenClaw should preserve that UUID as the canonical session identity.
Control UI and Open WebUI should read/write the same session entity, and
sessions.jsonshould not create a second record underagent:main:<uuid>.Actual behavior
One logical chat can become two separate OpenClaw session records:
<uuid>agent:main:<uuid>This is not just an alias/display issue. In the broken case, the two entries have different:
sessionIdsessionFileThat means the system is actually storing one logical chat as two backend sessions.
OpenClaw version
2026.3.13
Operating system
Ubuntu server
Install method
Self-hosted OpenClaw gateway with Open WebUI via Docker
Model
openai-codex/gpt-5.4
Provider / routing chain
Open WebUI -> local OpenAI-compatible proxy -> OpenClaw gateway -> openai-codex/gpt-5.4
Config file / key location
Relevant places:
~/.openclaw/agents/main/sessions/sessions.json~/.openclaw/agents/main/sessions/<sessionId>.jsonlsrc/gateway/session-utils.tssrc/gateway/server-methods/chat.tsui/src/ui/app-settings.tsAdditional provider/model setup details
Open WebUI was connected to OpenClaw through a local OpenAI-compatible proxy with stable chat/session IDs preserved across requests.
This does not appear to be a model/provider bug. It looks like a backend session canonicalization bug inside OpenClaw.
Logs, screenshots, and evidence
Key evidence:
sessions.jsoncontained two different records for the same logical chat:<uuid>agent:main:<uuid>And these were not two names for the same object. They pointed to different:
sessionIdsessionFileExample shape of the broken state:
sessionId: <id-a>sessionFile: <id-a>.jsonlsessionId: <id-b>sessionFile: <id-b>.jsonlThat shows the problem had already crossed from "wrong key display" into actual duplicated session storage.
Additional clue: the UI already contains a special workaround in
ui/src/ui/app-settings.ts:normalizeChatUrlSessionKey(...)agent:main:<uuid>back to<uuid>for opaque UUID chatsThat strongly suggests the frontend already knows these WebUI-backed UUID chats are special, while the backend still canonicalizes them too aggressively.
Impact and severity
Affected:
Severity:
Frequency:
Consequence:
Additional information
We traced the likely root cause and validated a local fix.
Root cause:
src/gateway/session-utils.ts, a bare UUID such as<uuid>was treated like a generic session key and canonicalized intoagent:main:<uuid>chat.sendinsrc/gateway/server-methods/chat.tsthen uses the canonicalized key, which allows Control UI writes to target a second backend entity instead of the original short-key sessionProposed fix
Apply a narrow backend fix:
src/gateway/session-utils.ts, if the session key is a bare opaque UUID used by WebUI-backed chats, preserve it as-is.<uuid>intoagent:main:<uuid>for that special case.agent:main:telegram:...agent:main:discord:...Files involved in the fix
src/gateway/session-utils.tssrc/gateway/server-methods/chat.tsui/src/ui/app-settings.tsLocal verification
We validated a local fix that preserves bare UUID keys for WebUI-backed chats:
agent:main:<uuid>for these chatsImportant note: