Triage note
This report is intentionally structured for automated/model triage: the reproduction is deterministic, the observed/expected behavior is explicit, and the suspected code path is called out separately from the observed evidence.
Bug type
Regression (worked before, now fails)
Beta release blocker
No
Summary
After upgrading from OpenClaw 2026.5.7 to 2026.5.18, cron agentTurn payloads using a configured non-Google provider model such as litellm/gemini-3-flash are rejected by cron preflight because the runtime allowlist is normalized to litellm/gemini-3-flash-preview.
Steps to reproduce
- Configure a custom/provider-backed model catalog entry under a non-Google LiteLLM-backed provider, for example
models.providers.litellm.models[].id = "gemini-3-flash".
- Add the same model to
agents.defaults.models as litellm/gemini-3-flash.
- Create a cron job with
sessionTarget = "isolated" and payload.kind = "agentTurn", setting payload.model = "litellm/gemini-3-flash".
- Force-run the cron job.
- Observe cron preflight rejecting the payload model because the effective allowlist contains
litellm/gemini-3-flash-preview instead of litellm/gemini-3-flash.
Expected behavior
A cron payload model should be accepted when it exactly matches a configured provider catalog entry and an agents.defaults.models allowlist entry for that same provider/model key.
In the observed setup, litellm/gemini-3-flash should remain litellm/gemini-3-flash because the configured provider is a custom LiteLLM-backed OpenAI-compatible provider. Google preview model-id normalization should not rewrite the model id unless the provider is Google/Google Gemini CLI/Google Vertex, or the configured provider explicitly opts into such normalization.
Actual behavior
On OpenClaw 2026.5.18, a delivery-none smoke cron using payload.model = "litellm/gemini-3-flash" failed at preflight. The diagnostic reported that litellm/gemini-3-flash was not in the allowlist, while the effective allowlist contained litellm/gemini-3-flash-preview and litellm/gemini-3.1-pro-preview.
This also affected real cron jobs that used litellm/gemini-3-flash as their payload model. Rolling back to OpenClaw 2026.5.7 made the same cron jobs run successfully without changing the cron jobs or the source config.
OpenClaw version
First known bad: 2026.5.12 / 2026.5.13 family; reproduced again on 2026.5.18.
Last known good: 2026.5.7.
Operating system
Linux 6.12.68+ x64, container/GKE-style runtime.
Install method
Containerized OpenClaw gateway runtime.
Model
litellm/gemini-3-flash as cron payload.model.
Provider / routing chain
OpenClaw cron isolated agent -> custom LiteLLM-backed provider -> OpenAI-compatible completions endpoint.
Additional provider/model setup details
Relevant source config uses non-preview model ids:
{
"models": {
"providers": {
"litellm": {
"api": "openai-completions",
"models": [
{ "id": "gemini-3-flash", "name": "Gemini 3 Flash" },
{ "id": "gemini-3.1-pro", "name": "Gemini 3.1 Pro" }
]
}
}
},
"agents": {
"defaults": {
"models": {
"litellm/gemini-3-flash": {},
"litellm/gemini-3.1-pro": {}
}
}
}
}
The issue is not that the provider cannot serve the model. The failure happens before dispatch, during cron model allowlist/preflight validation.
Logs, screenshots, and evidence
Observed timeline:
- On 2026.5.12/2026.5.13, source config and cron payloads both used non-preview
litellm/gemini-3-flash, but runtime cron preflight rejected payload.model = "litellm/gemini-3-flash" because the effective allowlist contained preview-normalized entries such as litellm/gemini-3-flash-preview and litellm/gemini-3.1-pro-preview.
- Rolling back to 2026.5.7 resolved the same cron jobs without changing cron/openclaw.json.
- On 2026.5.18, the regression reproduced again with a temporary delivery-none smoke cron using
payload.model = "litellm/gemini-3-flash".
Representative diagnostic, redacted/abridged:
cron payload.model 'litellm/gemini-3-flash' rejected by agents.defaults.models allowlist:
litellm/gemini-3-flash is not in [..., litellm/gemini-3-flash-preview, litellm/gemini-3.1-pro-preview, ...]
Likely code path from current openclaw/openclaw source (cd019cfa when checked):
src/plugin-sdk/provider-model-id-normalize.ts defines Google preview normalization, including gemini-3-flash -> gemini-3-flash-preview and gemini-3.1-pro -> gemini-3.1-pro-preview.
src/agents/model-ref-shared.ts is provider-scoped for this normalization in normalizeBuiltInProviderModelId(), applying it only for google, google-gemini-cli, and google-vertex.
- But
src/config/model-input.ts currently has normalizeAgentModelRefForConfig(model) split provider/model and then call normalizeGooglePreviewModelId() on the suffix regardless of provider:
const provider = normalizeProviderId(trimmed.slice(0, slash));
const normalizedModel = normalizeGooglePreviewModelId(trimmed.slice(slash + 1));
return modelKeyForConfig(provider, normalizedModel);
This can rewrite litellm/gemini-3-flash into litellm/gemini-3-flash-preview while preserving the non-Google provider prefix, which matches the observed runtime allowlist mismatch.
Cron then rejects the original payload model in src/cron/isolated-agent/model-selection.ts via resolveAllowedModelRef() / allowlist validation, producing the observed cron payload.model ... rejected by agents.defaults.models allowlist error.
Impact and severity
Affected: cron jobs that use payload.model with custom/non-Google LiteLLM-backed provider ids whose model ids happen to match Google Gemini preview-normalization aliases, e.g. litellm/gemini-3-flash.
Severity: High for affected installations because scheduled jobs fail before model dispatch.
Frequency: Always for the affected cron preflight path on 2026.5.18 in the observed setup.
Consequence: scheduled jobs silently accumulate cron preflight failures until the user changes the payload model, updates config, rolls back, or the normalization bug is fixed.
Additional information
Temporary workaround: migrate affected cron payloads away from litellm/gemini-3-flash to a non-affected configured model such as litellm/minimax-m2.5-aws or another model id that does not trigger Gemini preview normalization.
Interactive agent primary model paths may not fail the same way: in the observed setup, an interactive agent configured with litellm/gemini-3-flash was runtime-normalized and could still execute, but the effective model differed from source config. The hard failure was specifically reproduced in cron payload preflight.
Triage note
This report is intentionally structured for automated/model triage: the reproduction is deterministic, the observed/expected behavior is explicit, and the suspected code path is called out separately from the observed evidence.
Bug type
Regression (worked before, now fails)
Beta release blocker
No
Summary
After upgrading from OpenClaw 2026.5.7 to 2026.5.18, cron
agentTurnpayloads using a configured non-Google provider model such aslitellm/gemini-3-flashare rejected by cron preflight because the runtime allowlist is normalized tolitellm/gemini-3-flash-preview.Steps to reproduce
models.providers.litellm.models[].id = "gemini-3-flash".agents.defaults.modelsaslitellm/gemini-3-flash.sessionTarget = "isolated"andpayload.kind = "agentTurn", settingpayload.model = "litellm/gemini-3-flash".litellm/gemini-3-flash-previewinstead oflitellm/gemini-3-flash.Expected behavior
A cron payload model should be accepted when it exactly matches a configured provider catalog entry and an
agents.defaults.modelsallowlist entry for that same provider/model key.In the observed setup,
litellm/gemini-3-flashshould remainlitellm/gemini-3-flashbecause the configured provider is a custom LiteLLM-backed OpenAI-compatible provider. Google preview model-id normalization should not rewrite the model id unless the provider is Google/Google Gemini CLI/Google Vertex, or the configured provider explicitly opts into such normalization.Actual behavior
On OpenClaw 2026.5.18, a delivery-none smoke cron using
payload.model = "litellm/gemini-3-flash"failed at preflight. The diagnostic reported thatlitellm/gemini-3-flashwas not in the allowlist, while the effective allowlist containedlitellm/gemini-3-flash-previewandlitellm/gemini-3.1-pro-preview.This also affected real cron jobs that used
litellm/gemini-3-flashas their payload model. Rolling back to OpenClaw 2026.5.7 made the same cron jobs run successfully without changing the cron jobs or the source config.OpenClaw version
First known bad: 2026.5.12 / 2026.5.13 family; reproduced again on 2026.5.18.
Last known good: 2026.5.7.
Operating system
Linux 6.12.68+ x64, container/GKE-style runtime.
Install method
Containerized OpenClaw gateway runtime.
Model
litellm/gemini-3-flashas cronpayload.model.Provider / routing chain
OpenClaw cron isolated agent -> custom LiteLLM-backed provider -> OpenAI-compatible completions endpoint.
Additional provider/model setup details
Relevant source config uses non-preview model ids:
{ "models": { "providers": { "litellm": { "api": "openai-completions", "models": [ { "id": "gemini-3-flash", "name": "Gemini 3 Flash" }, { "id": "gemini-3.1-pro", "name": "Gemini 3.1 Pro" } ] } } }, "agents": { "defaults": { "models": { "litellm/gemini-3-flash": {}, "litellm/gemini-3.1-pro": {} } } } }The issue is not that the provider cannot serve the model. The failure happens before dispatch, during cron model allowlist/preflight validation.
Logs, screenshots, and evidence
Observed timeline:
litellm/gemini-3-flash, but runtime cron preflight rejectedpayload.model = "litellm/gemini-3-flash"because the effective allowlist contained preview-normalized entries such aslitellm/gemini-3-flash-previewandlitellm/gemini-3.1-pro-preview.payload.model = "litellm/gemini-3-flash".Representative diagnostic, redacted/abridged:
Likely code path from current
openclaw/openclawsource (cd019cfawhen checked):src/plugin-sdk/provider-model-id-normalize.tsdefines Google preview normalization, includinggemini-3-flash->gemini-3-flash-previewandgemini-3.1-pro->gemini-3.1-pro-preview.src/agents/model-ref-shared.tsis provider-scoped for this normalization innormalizeBuiltInProviderModelId(), applying it only forgoogle,google-gemini-cli, andgoogle-vertex.src/config/model-input.tscurrently hasnormalizeAgentModelRefForConfig(model)splitprovider/modeland then callnormalizeGooglePreviewModelId()on the suffix regardless of provider:This can rewrite
litellm/gemini-3-flashintolitellm/gemini-3-flash-previewwhile preserving the non-Google provider prefix, which matches the observed runtime allowlist mismatch.Cron then rejects the original payload model in
src/cron/isolated-agent/model-selection.tsviaresolveAllowedModelRef()/ allowlist validation, producing the observedcron payload.model ... rejected by agents.defaults.models allowlisterror.Impact and severity
Affected: cron jobs that use
payload.modelwith custom/non-Google LiteLLM-backed provider ids whose model ids happen to match Google Gemini preview-normalization aliases, e.g.litellm/gemini-3-flash.Severity: High for affected installations because scheduled jobs fail before model dispatch.
Frequency: Always for the affected cron preflight path on 2026.5.18 in the observed setup.
Consequence: scheduled jobs silently accumulate cron preflight failures until the user changes the payload model, updates config, rolls back, or the normalization bug is fixed.
Additional information
Temporary workaround: migrate affected cron payloads away from
litellm/gemini-3-flashto a non-affected configured model such aslitellm/minimax-m2.5-awsor another model id that does not trigger Gemini preview normalization.Interactive agent primary model paths may not fail the same way: in the observed setup, an interactive agent configured with
litellm/gemini-3-flashwas runtime-normalized and could still execute, but the effective model differed from source config. The hard failure was specifically reproduced in cron payload preflight.