Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Responses API: undocumented reasoning+message pairing constraint breaks multi-turn conversations

Aperta
#710 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
35/100
Tipo di issue
Bug
Chiarezza
Da chiarire
Stato di attività
Tranquilla
Stack tecnologico
java
Ambito
api

Direzione di ricerca

Inizia con il flusso della Responses API mostrato in PairingConstraintRepro, in particolare con ResponseInputUnionParam, ResponseCreateParams, response.output() e previousResponseId(). Riproduci il fallimento del secondo turno con i modelli elencati e determina se la soluzione debba appartenere a questo SDK o all’API; il lavoro sarà completato quando saranno chiaramente identificati una responsabilità verificabile e un cambiamento del comportamento testabile.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug spec

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 Java, JS, Python, Go, .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:

  • openai/openai-openapi#536 (spec root cause)
  • openai/openai-node#1791 (same bug, Node SDK)
  • openai/openai-python#TBD (same bug, Python SDK)
  • openai/openai-dotnet#TBD (same bug, .NET SDK)
  • openai/openai-go#TBD (same bug, Go SDK)
  • openclaw/openclaw#49167 (64.9k forks, production breakage)
To Reproduce
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.*;

import java.util.ArrayList;
import java.util.List;

public class PairingConstraintRepro {
    public static void main(String[] args) {
        OpenAIClient client = OpenAIOkHttpClient.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .build();

        String[] prompts = {"Write a Python prime checker.", "Add type hints.", "Add docstrings."};
        List<ResponseInputUnionParam> conversation = new ArrayList<>();

        for (String msg : prompts) {
            System.out.println("\n> " + msg);
            conversation.add(ResponseInputUnionParam.ofEasyInputMessage(
                EasyInputMessageParam.builder()
                    .role(EasyInputMessageParam.Role.USER)
                    .content(msg)
                    .build()));

            try {
                Response response = client.responses().create(
                    ResponseCreateParams.builder()
                        .model("gpt-5.3-codex")
                        .input(ResponseCreateParams.Input.ofResponseInputs(conversation))
                        .maxOutputTokens(300)
                        .reasoning(Reasoning.builder().effort(Reasoning.Effort.HIGH).build())
                        .build());

                // Common pattern: keep only messages, discard reasoning
                for (ResponseOutputItem item : response.output()) {
                    if (item.isMessage()) {
                        // Convert output message to input — orphan message → 400
                        conversation.add(ResponseInputUnionParam.ofResponseInputItem(
                            ResponseInputItemParam.builder()
                                .id(item.asMessage().id())
                                .type(ResponseInputItemParam.Type.MESSAGE)
                                .build()));
                    }
                }
            } catch (Exception e) {
                System.out.println("  ERROR: " + e.getMessage().substring(0, Math.min(120, e.getMessage().length())));
                break;
            }
        }
        // Turn 2 → 400: Item 'msg_...' was provided without its required preceding item
    }
}

Note: the Java 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

Java version

Java 21

Library version

openai-java v4.29.0

Lingua principale
Kotlin
Stelle
1.5k
Fork
264
Merge medio
13h 31m
PR unite (30g)
89

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di openai/openai-java

Tutte le issue di openai/openai-java

Issue simili

Altre issue su Kotlin

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.