Reasoning+message items must appear as consecutive pairs in input, but nothing documents this. The most common pattern — filtering response.Output to keep only messages — silently produces orphaned items → 400 on the next turn.
This broke OpenClaw (64.9k forks) on gpt-5.3-codex. They had to add downgradeOpenAIReasoningBlocks() to strip orphan reasoning items.
400: Item 'msg_...' of type 'message' was provided without its required preceding item of type 'reasoning'
Tested in Go, JS, Python, Java, .NET — identical results across all 5 SDKs. This is an API-level constraint, not SDK-specific. Confirmed via curl (see gist). The SDK types don't prevent building input arrays that violate it.
| Model |
A (all items) |
B (msgs only) |
| gpt-5.3-codex (reasoning=high) |
PASS |
FAIL |
| o4-mini |
PASS |
FAIL* |
* Nondeterministic — o4-mini sometimes returns reasoning-only output (no message to orphan). Codex with reasoning=high reliably returns both items.
Workaround: PreviousResponseID. For manual history, always pass reasoning+message pairs together.
Related:
To Reproduce
package main
import (
"context"
"fmt"
"os"
"github.com/openai/openai-go"
"github.com/openai/openai-go/responses"
)
func main() {
client := openai.NewClient(openai.WithAPIKey(os.Getenv("OPENAI_API_KEY")))
ctx := context.Background()
prompts := []string{"Write a Python prime checker.", "Add type hints.", "Add docstrings."}
var conversation []responses.ResponseInputUnionParam
for _, msg := range prompts {
fmt.Printf("\n> %s\n", msg)
conversation = append(conversation, responses.ResponseInputUnionParam{
OfEasyInputMessage: &responses.EasyInputMessageParam{
Role: "user",
Content: responses.EasyInputMessageContentUnionParam{OfString: &msg},
},
})
resp, err := client.Responses.New(ctx, responses.ResponseNewParams{
Model: "gpt-5.3-codex",
Input: responses.ResponseNewParamsInputUnion{OfResponseInputs: conversation},
MaxOutputTokens: openai.Int(300),
Reasoning: &responses.ReasoningParam{
Effort: "high",
},
})
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
break
}
// Common pattern: keep only messages, discard reasoning
for _, item := range resp.Output {
if item.Type == "message" {
conversation = append(conversation, responses.ResponseInputUnionParam{
OfMessage: &responses.ResponseInputMessageParam{
ID: item.ID,
Type: "message",
Role: "assistant",
Content: item.Content, // needs conversion in practice
},
})
}
}
}
// Turn 2 → 400: Item 'msg_...' was provided without its required preceding item
}
Note: the Go SDK's distinct input/output wrapper types make the conversion verbose, but the pairing constraint failure is the same regardless.
Reproduced on o4-mini and gpt-5.3-codex. Full cross-language repro (JS, Python, .NET, curl): https://gist.github.com/achandmsft/57886350885cec3af8ef3f456ed529cf
OS
Windows 11, also reproduced on Linux
Go version
Go 1.24
Library version
openai-go v3.29.0
Reasoning+message items must appear as consecutive pairs in
input, but nothing documents this. The most common pattern — filteringresponse.Outputto keep only messages — silently produces orphaned items → 400 on the next turn.This broke OpenClaw (64.9k forks) on
gpt-5.3-codex. They had to adddowngradeOpenAIReasoningBlocks()to strip orphan reasoning items.Tested in Go, JS, Python, Java, .NET — identical results across all 5 SDKs. This is an API-level constraint, not SDK-specific. Confirmed via curl (see gist). The SDK types don't prevent building
inputarrays that violate it.* Nondeterministic — o4-mini sometimes returns reasoning-only output (no message to orphan). Codex with reasoning=high reliably returns both items.
Workaround:
PreviousResponseID. For manual history, always pass reasoning+message pairs together.Related:
To Reproduce
Note: the Go SDK's distinct input/output wrapper types make the conversion verbose, but the pairing constraint failure is the same regardless.
Reproduced on o4-mini and gpt-5.3-codex. Full cross-language repro (JS, Python, .NET, curl): https://gist.github.com/achandmsft/57886350885cec3af8ef3f456ed529cf
OS
Windows 11, also reproduced on Linux
Go version
Go 1.24
Library version
openai-go v3.29.0