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.
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.
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.
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
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’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.
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.
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:
<?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.";
}
?>