Skip to content

Session bootstrap race condition sends zero messages to zai/glm-5.1 causing 400 error #73683

Description

@lhtpluto

Bug Description

When a new webchat session starts, the first API request to the LLM provider is sent before the bootstrap user message is written to the session file. This results in prompt.submitted having messages: [] (zero conversation messages, only a system prompt).

Models that tolerate a system-only request (e.g., bailian/qwen3.6-plus) succeed. But models that require at least one non-system message (e.g., zai/glm-5.1, zai/glm-5-turbo) reject the request with a 400 error:

400 messages 参数非法。请检查文档。

After the initial failure, the bootstrap message is written to the session file, and subsequent fallback requests succeed.

Steps to Reproduce

  1. Configure zai provider with a GLM-5.1 or GLM-5-Turbo model as the primary model
  2. Start a new webchat session (/new or /reset)
  3. Observe that the first API request fails with 400, then fallback succeeds

Root Cause Analysis

I traced through the trajectory files of 5 failed session boots. Every single one shows the same pattern:

Trajectory evidence

Failed request (zai/glm-5.1):

prompt.submitted -> messages=0, system_prompt_len=49637

The prompt.submitted event confirms the request was sent with zero conversation messages. After the failure, the bootstrap messages are written, and the fallback request sees them.

Confirmed affected sessions

Time (UTC) Session File Model prompt.submitted messages Result
2026-04-28 14:14:22 3eb9302f glm-5.1 0 400
2026-04-28 15:24:10 6c5dfb28 glm-5.1 0 400
2026-04-28 15:49:15 0a26d71f glm-5.1 0 400
2026-04-28 16:02:59 24c66d4c glm-5-turbo 0 400
2026-04-28 16:06:24 e5421c47 glm-5.1 0 400

Successful comparison

The same session that failed for glm-5.1 at 23:49 later succeeded with glm-5-turbo at 00:01 with 63 messages (after bootstrap messages were written).

API endpoint verification

I confirmed the error is reproducible with direct API calls:

# Only system message -> 400 (matches the log error exactly)
curl ... -d "{\"model\":\"glm-5.1\",\"messages\":[{\"role\":\"system\",\"content\":\"You are an assistant.\"}]}"
# -> {"error":{"code":"1214","message":"messages 参数非法。请检查文档。"}}

# With user message -> 200 OK
curl ... -d "{\"model\":\"glm-5.1\",\"messages\":[{\"role\":\"system\",\"content\":\"You are an assistant.\"},{\"role\":\"user\",\"content\":\"hello\"}]}"
# -> 200 OK

# Empty messages array -> different error
curl ... -d "{\"model\":\"glm-5.1\",\"messages\":[]}"
# -> {"error":{"code":"1214","message":"输入不能为空"}}

The zai Coding Plan endpoint requires at least one user or assistant message. The bug is on the OpenClaw side sending the request before bootstrap messages exist.

Why it was not noticed before

  1. Model tolerance: Previously used models like bailian/qwen3.6-plus accept system-only requests and generate a greeting.
  2. glm-4.7 tolerance: GLM-4.7 on the same Coding Plan endpoint may also be more lenient.
  3. glm-5.1/5-turbo strictness: These newer models enforce a stricter messages schema.

Suggested Fix

Ensure the bootstrap user message is written to the session file before the first API request is made. Options:

  1. Pre-write bootstrap message: Write (session bootstrap) during session.started handling, before the first prompt.submitted.
  2. Synthetic bootstrap message: If the session file is empty at request time, inject a synthetic user message into the messages array sent to the provider.
  3. Await bootstrap completion: Ensure the first API request waits for the bootstrap message write to complete.

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions