Bug Description
When configuring a custom OpenAI-compatible API provider (e.g., spanagent.xyz), if the baseUrl is set to https://spanagent.xyz (without /v1 suffix), OpenClaw constructs the request URL as https://spanagent.xyz/chat/completions. This endpoint returns an HTML page (200 OK, Content-Type: text/html), which the streaming handler cannot parse. The error surfaced to the user is cryptic:
FailoverError: spanagent/deepseek-v4-flash ended with an incomplete terminal response
Meanwhile, the log shows contentType=text/html; charset=utf-8 but no clear indication that the URL path is wrong.
Steps to Reproduce
- Add a custom provider via
openclaw onboard or manual config:
{
"baseUrl": "https://spanagent.xyz",
"api": "openai-completions",
"models": [{ "id": "deepseek-v4-flash", "reasoning": true, ... }]
}
- Run
openclaw agent --agent <agent> --message "hi" --model <provider>/deepseek-v4-flash --local
- Observe: request goes to
https://spanagent.xyz/chat/completions (no /v1 prefix)
- API returns HTML page with 200 OK
- Error:
incomplete terminal response — no mention of wrong URL
Expected Behavior
- The onboard wizard or docs should guide users to use
https://spanagent.xyz/v1 as the base URL (OpenAI SDK appends /chat/completions to the base URL)
- When the provider returns non-JSON/non-SSE content (e.g., HTML), the error should be descriptive: "API endpoint returned HTML instead of a valid response — check baseUrl (should typically end with /v1 for OpenAI-compatible APIs)"
Actual Behavior
Silent failure with misleading incomplete terminal response message. Requires log inspection to find contentType=text/html and discover the wrong URL path.
Environment
- OpenClaw version: 2026.5.19-beta.1 (167e73c)
- Deployment: Docker container (npm global install)
- Provider: Custom OpenAI-compatible API (spanagent.xyz)
Additional Context
The OpenAI JavaScript SDK (used internally by pi-ai/pi-agent-core) constructs the endpoint URL as ${baseUrl}/chat/completions. This means for any provider serving under a path prefix (like /v1/), the baseUrl MUST include that prefix.
For example:
- ❌
https://spanagent.xyz → request goes to https://spanagent.xyz/chat/completions (wrong)
- ✅
https://spanagent.xyz/v1 → request goes to https://spanagent.xyz/v1/chat/completions (correct)
A secondary issue was also encountered: the default maxTokens of 384000 for deepseek models exceeded the providers limit (65536), causing HTTP 400. The error message for this was clear (400 field MaxTokens invalid, should be in [1, 65536]), so that part is fine — just noting the config guidance gap.
Bug Description
When configuring a custom OpenAI-compatible API provider (e.g.,
spanagent.xyz), if thebaseUrlis set tohttps://spanagent.xyz(without/v1suffix), OpenClaw constructs the request URL ashttps://spanagent.xyz/chat/completions. This endpoint returns an HTML page (200 OK, Content-Type: text/html), which the streaming handler cannot parse. The error surfaced to the user is cryptic:Meanwhile, the log shows
contentType=text/html; charset=utf-8but no clear indication that the URL path is wrong.Steps to Reproduce
openclaw onboardor manual config:{ "baseUrl": "https://spanagent.xyz", "api": "openai-completions", "models": [{ "id": "deepseek-v4-flash", "reasoning": true, ... }] }openclaw agent --agent <agent> --message "hi" --model <provider>/deepseek-v4-flash --localhttps://spanagent.xyz/chat/completions(no/v1prefix)incomplete terminal response— no mention of wrong URLExpected Behavior
https://spanagent.xyz/v1as the base URL (OpenAI SDK appends/chat/completionsto the base URL)Actual Behavior
Silent failure with misleading
incomplete terminal responsemessage. Requires log inspection to findcontentType=text/htmland discover the wrong URL path.Environment
Additional Context
The OpenAI JavaScript SDK (used internally by pi-ai/pi-agent-core) constructs the endpoint URL as
${baseUrl}/chat/completions. This means for any provider serving under a path prefix (like/v1/), the baseUrl MUST include that prefix.For example:
https://spanagent.xyz→ request goes tohttps://spanagent.xyz/chat/completions(wrong)https://spanagent.xyz/v1→ request goes tohttps://spanagent.xyz/v1/chat/completions(correct)A secondary issue was also encountered: the default
maxTokensof 384000 for deepseek models exceeded the providers limit (65536), causing HTTP 400. The error message for this was clear (400 field MaxTokens invalid, should be in [1, 65536]), so that part is fine — just noting the config guidance gap.