Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

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

Abierto
#710 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Necesita aclaración
Estado de actividad
Tranquilo
Stack tecnológico
java
Área
api

Línea de trabajo

Comienza con el flujo de la Responses API mostrado en PairingConstraintRepro, especialmente con ResponseInputUnionParam, ResponseCreateParams, response.output() y previousResponseId(). Reproduce el fallo del segundo turno con los modelos indicados y determina si la solución corresponde a este SDK o a la API; el trabajo estará terminado cuando haya una asignación de responsabilidad y un cambio de comportamiento claramente identificados y comprobables.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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

Lenguaje dominante
Kotlin
Estrellas
1.5k
Forks
264
Merge medio
13 h 31 min
PR fusionados (30 d)
89

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de openai/openai-java

Todos los issues de openai/openai-java

Issues similares

Más issues de Kotlin

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.