Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

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

オープン
#710 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
説明が足りない
活発さ
静か
技術スタック
java
領域
api

調査の方向性

PairingConstraintRepro に示されている Responses API のフローから始め、特に ResponseInputUnionParam、ResponseCreateParams、response.output()、previousResponseId() を確認してください。記載されたモデルで 2 ターン目の失敗を再現し、対応がこの SDK に属するのか API に属するのかを判断してください。明確に特定された、テスト可能な担当範囲と動作変更が得られれば完了です。

索引モデルが issue の本文から書いたものです。

説明

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

主要言語
Kotlin
スター
1.5k
フォーク
266
平均マージ
10時間 11分
マージ済み PR(30日)
141

環境構築

Codespaces で開く

このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

openai/openai-java のほかの issue

openai/openai-java の issue をすべて見る

似ている issue

Kotlin の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。