Skip to content

OpenAI requests return 'extra_body' unknown parameter error when no extra_body is providedΒ #5196

@andrewigk

Description

@andrewigk

Environment
Spring AI 1.1.1+ produces this issue, no issues in prior versions

Steps to reproduce
Attempt to create and use Chat Client based on how the OpenAI chat model is initialized here:

public OpenAiChatModel getOpenAiCompatibleChatModel(final ChatSettings settings) throws IllegalArgumentException {

        final String providerBaseUrl;
        final String providerApiKey;
        final String providerCompletionsPath;

        switch (settings.getModel().getProvider()) {
            case OPENAI:
                providerBaseUrl = providerConfig.getOpenAiBaseUrl();
                providerApiKey = providerConfig.getOpenAiApiKey();
                providerCompletionsPath = providerConfig.getOpenAiCompletionsPath();
                break;
            case PERPLEXITY:
                providerBaseUrl = providerConfig.getPerplexityBaseUrl();
                providerApiKey = providerConfig.getPerplexityApiKey();
                providerCompletionsPath = providerConfig.getPerplexityCompletionsPath();
                break;
            default:
                throw new IllegalArgumentException(
                        "Unknown OpenAI-compatible provider: " + settings.getModel().getProvider().name());
        }

        final OpenAiApi api = new OpenAiApi.Builder()
            .baseUrl(providerBaseUrl)
            .apiKey(providerApiKey)
            .completionsPath(providerCompletionsPath)
            .build();

        final Builder optsBuilder = OpenAiChatOptions
            .builder()
            .model(settings.getModel().getName())
            .temperature(settings.getTemperature().getValue());

        if (settings.getReasoningEffort() != null) {
            optsBuilder.reasoningEffort(settings.getReasoningEffort().getValue());
        }

        if (settings.getVerbosity() != null) {
            optsBuilder.verbosity(settings.getVerbosity().getValue());
        }

        final OpenAiChatOptions opts = optsBuilder.build();

        return OpenAiChatModel.builder().openAiApi(api).defaultOptions(opts).build();
    }

Expected behavior
The request should fail, returning this error:
17:58:10,218 WARN [org.springframework.ai.retry.RetryUtils] 9759c677-2b01-452b-a3bd-4111c396b7ca#633601 - Retry error. Retry count:1 org.springframework.ai.retry.NonTransientAiException: 400 - { "error": { "message": "Unknown parameter: 'extra_body'.", "type": "invalid_request_error", "param": "extra_body", "code": "unknown_parameter" } }

Did something change that would break this? I've changed nothing other than upgrade my Spring AI version, so I wonder if some parameter that is being set is no longer supported/recognized, and being converted into an extra_body parameter or something.

Investigation
See this commit for v1.1.0: 3fc939a

If extra_body is null, it is set to create a mutable, empty map for the purposes of deserialization using JsonAnySetter. However, I doubt that this was tested thoroughly because the JsonProperty annotation wasn't even present on ChatCompletionRequest until v1.1.1. I believe this to be an issue because OpenAI will throw an error to any unrecognized parameter, whether it is null or empty. The tests, while logically sound, do not account for the real-world usage of making the request to OpenAI API while passing an empty extra_body object, which produce errors.

See this commit for v1.1.1: 0646d1e

It seems most likely that the changes made in v1.1.0 were not tested properly because extra_body wasn't being included properly in a ChatCompletionRequest anyway, and since the v1.1.1 change that adds the annotation necessary, the mandatory inclusion of an empty extra_body object that is NOT being excluded in the request body is causing issues when making requests to OpenAI.

Contrary to what the documentation states, the official OpenAI API does not ignore unrecognized parameters... it fully rejects them and results in an error.

However, when logging the toString() output of OpenAiChatOptions right before using the OpenAiChatModel builder, the output does not show any signs of extra_body:
OpenAiChatOptions: {"streamUsage":false,"model":"gpt-5-mini","temperature":1.0}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions