Getting strange UnrecognizedKwargsError error

As far as I can tell ChatGPT is calling my API with exactly the right type of request. I can even use curl to verify the JSON is valid. But I always get this strange UnrecognizedKwargsError error from ChatGPT.

My understanding is that this error was NOT generated by my codes. But it was generated by some backend magic from OpenAI? I suppose there were some python codes executed by OpenAI and they gave me this error.

is there any tool (actually I can’t find the debug my local plugin tool anymore) or method for me to debug this? I have spent hours tweaking my json and yaml files to no avail.

Your help will be greatly appreciated!

2 Likes

My bad. I found out the debugging tool must be enabled in the settings. It would be nice if it is auto-displayed after I installed the local plugin.

From the debugging panel, I can see that OpenAI somehow was not able to properly parse the type for my new endpoint:

type query_classify_contract_post = () => any;

It simply was not able to find any structure that I defined. However, all other endpoints are parsed correctly, like this one:

type query_asset_pricing_post = (_: {
assets: any,
currency?: string,
}) => any;

As far as I can tell, for these two endpoints I am doing exactly the same thing. :frowning:

Can I provide this parsed js codes to OpenAi directly or hint it somehow?

I get this error when ChatGPT erroneously tries to POST a string to the API when it is defined as an object in the OpenAPI spec. Renaming the object property seemed to have worked in solving this.

4 Likes

I managed to get around this. In short, I think I have to define the object structure explicitly. So I want to implement a generic service that takes a sequence of KV pairs and do something with them. But it seems that openapi requires us to spell out each K and V in details. Not a deal breaker, but slightly odd.

I’m getting the same error. My OpenAPI spec is below and what it’s choking on is the “from” parameter, which is defined as an object. There is a schema referenced to further define the “from” object, but that does not seem to be enough.

openapi: 3.0.0
info:
  title: Transactional API
  description: MailChannels Send API allows you to send emails.
  version: 0.2.0
  contact:
    name: MailChannels Corporation
    email: support@mailchannels.com

servers:
  - url: 'https://api.mailchannels.net/tx/v1'

paths:
  /send:
    post:
      operationId: send
      summary: Send a message over the MailChannels API
      description: Send emails by making HTTP requests to the API.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MailSendBody'
      responses:
        '202':
          description: Success
        '400':
          description: Bad Request
        '413':
          description: |
            Payload too large - The total message size should not exceed 20MB.
            This includes the message itself, headers, and the combined size of any attachments.
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    EmailAddress:
      type: object
      required:
        - email
      properties:
        email:
          type: string
          example: firstname.lastname@example.com
        name:
          type: string
          example: FirstName LastName
    ContentItem:
      type: object
      description: |
        The content of the message you are sending. This can be text, HTML, or a combination of both.
        text/plain and text/html are the only accepted mime types, and text/plain must be present
        before text/html. Each may appear exactly once.
      required:
        - type
        - value
      properties:
        type:
          description: The mime type of the content you are including in your email
          type: string
          example: text/plain
        value:
          description: The actual content of the specified mime type that you are including in the message
          type: string
    Personalization:
      required:
        - to
      description: |
        An object that contains the recipient(s) of the email, along with other metadata about the message,
        including the sender, subject, and custom headers. Each personalization object can be thought
        of as an envelope - it defines who should receive an individual message and how that message
        should be handled.
      example:
        to:
          - email: fistname.lastname@example.com
            name: FirstName LastName
        from:
          email: sender@example.com
          name: Sender Name
        subject: Hello World
        content:
          - type: text/plain
            value: Hello World! I am sending an email
          - type: text/html
            value: <html><body><p>Hello World! I am sending an email</p></body></html>
      properties:
        to:
          type: array
          minItems: 1
          maxItems: 1000
          items:
            $ref: '#/components/schemas/EmailAddress'
        from:
          type: object
          allOf:
            - $ref: '#/components/schemas/EmailAddress'
        reply_to:
          type: object
          allOf:
            - $ref: '#/components/schemas/EmailAddress'
        cc:
          type: array
          maxItems: 1000
          items:
            $ref: '#/components/schemas/EmailAddress'
        bcc:
          type: array
          maxItems: 1000
          items:
            $ref: '#/components/schemas/EmailAddress'
        subject:
          type: string
        headers:
          description: |
            A JSON object containing key/value pairs of header names and the value to substitute for them.
            The Key/value pairs must be strings. You must ensure these are properly encoded if they
            contain unicode characters. Must not be one of the reserved headers (received, dkim-signature,
            Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC, Authentication-Results,
            Message-ID).
          type: object
          additionalProperties:
            type: string
          example: { "X-My-Custom-Header": "My custom value" }
    MailSendBody:
      type: object
      required:
        - personalizations
        - from
        - subject
        - content
      properties:
        personalizations:
          type: array
          maxItems: 1000
          items:
            $ref: '#/components/schemas/Personalization'
        from:
          type: object
          allOf:
            - $ref: '#/components/schemas/EmailAddress'
        reply_to:
          type: object
          allOf:
            - $ref: '#/components/schemas/EmailAddress'
        subject:
          type: string
        content:
          type: array
          items:
            $ref: '#/components/schemas/ContentItem'
        headers:
          description: |
            A JSON object containing key/value pairs of header names and the value to substitute for them.
            The Key/value pairs must be strings. You must ensure these are properly encoded if they
            contain unicode characters. Must not be one of the reserved headers (received, dkim-signature,
            Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC, Authentication-Results,
            Message-ID).
          type: object
          additionalProperties:
            type: string
          example: { "X-My-Custom-Header": "My custom value" }
    ErrorResponse:
      type: object
      properties:
        errors:
          description: >
            This is an array error objects that provide machine and human readable descriptions of
            the errors.
          type: array
          items:
            type: string
            example: "The 'from' address in MailSendBody is required"

What’s your in server logs? The plugin might be making a malformed request. Like GET when it needs to be post or just the wrong endpoint.

Include in the description of your endpoints the context in which these endpoints should be used. Like when /sendemail [body] is typed, this will help test it by forcing certain functions.

I have tested the exact request that ChatGPT said it was sending and the test passes just fine. There is nothing wrong with ChatGPT’s request, in other words.

The problem is that ChatGPT’s client code is generating this error and not calling the API at all.

2 Likes

YMMV, but I have noticed cases where quart_cors supports an endpoint openapi.yaml (as tested by curl), but chatGPT doesn’t seem to parse the yaml correctly, and sends an incorrectly formed url.
Also, for what it’s worth, if you use Chrome and open developer tools, with a bit of breakpointing and tracing you can often find a failure message where client-side javascript is failing to parse the yaml, and will list the specific error

The JavaScript code is, of course, minified and obscured, making it super tough to breakpoint effectively. Thanks for the idea, though!

Yeah, very tedious. My process is to step at current level till I realized I passed something interesting, set a breakpoint at the previous step, and restart. very very tedious, but I can often find a specific text error msg buried deep down.

I found out the debugging tool must be enabled in the settings

Hey, I’m having the same issue. What tool is this? Could you point me to what settings and where you enabled this? Thanks!

Looks like it’s gone missing :male_detective: The devtools option is missing

I’ve just stumbled into this and after checking the example repo it seems that you need to explicitly specify the parameters that are going to be passed to each of the plugin’s API endpoints.

This is not very clear on the documentation, specially on the openapi.yaml definition part of it.

From the example repo:

/todos/{username}:
    get:
      operationId: getTodos
      summary: Get the list of todos
      parameters:
      - in: path
        name: username
        schema:
            type: string
        required: true
        description: The name of the user.
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/getTodosResponse'

It seems OpenAI engineers haven’t looked into the problem. It still exists in the new GPT platform.

The requirement of explicitly specified attributes is not only annoying but also dysfunctional. Why? I could explicitly specify them, but that will increase the file size of the OpenAPI spec. When the size is big, the GPT will crash because the platform apparently sets a size limit on the spec.

Any solution to UnrecognizedKwargsError?

Just so we’re entirely clear, you can define your OpenAPI schema to accept arbitrary key-value pairs with additionalProperties / patternProperties / unevaluatedProperties.

It’s not unreasonable for OpenAI to request that you define a schema for your requests and responses, this helps a lot with making sure that the requests ChatGPT makes are well-formed.

I’ve been struggling with this issue myself, and I’m seeing in the debugging logs that it’s using params , which could be correct, but it seems that it might not.

Shouldn’t it use something like body? Like the body of the post request?

I created an issue here (id 557653) and dumped my schema in case someone wants to reproduce it.

2 Likes

This is 99% likely a problem with the openAPI schema. I have experience creating several API action connections using ChatGPT custom bots, and I can tell you that it’s most likely an improper schema causing this error, having received the SAME error myself and solving it by fixing my schema.

I encountered the exact same problem when toying around with invoking a POST request from a custom GPT. I was using this simple PHP code:

<?php // Check if the request method is POST if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Assuming the string to append is sent as a parameter named 'data' if (isset($_POST['data'])) { $data = $_POST['data'] . "\n"; // Add a newline for each entry for readability // Open the file in append mode, create it if it doesn't exist $file = fopen("data.txt", "a"); // Write the data to the file fwrite($file, $data); // Close the file fclose($file); echo "Data appended successfully."; } else { echo "No data to append."; } } else { // Not a POST request echo "This script only handles POST requests."; } ?>

While curl -X POST -d ‘data=Hello, World’ https://myserver.com/post.php worked nicely, it never did work in a custom GPT action.

What helped me was to embed the payload and make it more complex. Here’s the curl example:

curl -X POST [URL]
-H “Content-Type: application/json”
-d ‘{“data”: {“name”: “John Doe”, “text”: “Hello, world!”}}’

and this is the corresponding code on the server:

<?php // Check if the request method is POST if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Get the raw POST data from the input stream $rawData = file_get_contents("php://input"); // Decode the JSON input into an associative array $jsonData = json_decode($rawData, true); // Check if the data object exists and has the required fields if (isset($jsonData['data']) && isset($jsonData['data']['text']) && isset($jsonData['data']['name'])) { // Concatenate the name and text with a newline for readability $dataToAppend = "Name: " . $jsonData['data']['name'] . " - Text: " . $jsonData['data']['text'] . "\n"; // Open the file in append mode, create it if it doesn't exist $file = fopen("data.txt", "a"); // Write the data to the file fwrite($file, $dataToAppend); // Close the file fclose($file); echo "Data appended successfully."; } else { echo "Invalid or incomplete JSON data."; } } else { // Not a POST request echo "This script only handles POST requests."; } ?>