-
Couldn't load subscription status.
- Fork 27
Description
Bug Report: @vercel/sdk createProjectEnv throws ResponseValidationError on Successful API Call
Title:
Bug: @vercel/sdk createProjectEnv throws ResponseValidationError on a successful (HTTP 201) API response due to an outdated Zod schema.
Affected Package:
@vercel/sdk
Version:
1.8.1 (as seen in logs: @vercel+sdk@1.8.1_zod@3.25.55)
Summary
When using the vercel.projects.createProjectEnv() method (especially with the upsert: 'true' option), the Vercel API correctly processes the request and returns a successful HTTP 201 Created status.
However, the Node.js application crashes because the SDK's internal response validation fails. The ResponseValidationError wraps a ZodError, indicating that the shape of the successful API response no longer matches the SDK's built-in Zod schema.
This is a client-side SDK bug that prevents developers from correctly handling a successful API operation.
Steps to Reproduce
- Use
@vercel/sdkversion1.8.1. - Execute the
vercel.projects.createProjectEnv()method. Theupsert: 'true'flag makes this easy to reproduce. - Ensure the call is valid and that the Vercel API returns a successful
HTTP 201response. - Observe the Node.js application throwing a fatal
ResponseValidationError.
Minimal Code Example:
import { Vercel } from '@vercel/sdk';
const vercel = new Vercel({
bearerToken: process.env.VERCEL_API_TOKEN,
});
async function upsertAndDeploy(projectId, envKey, envValue) {
try {
console.log(`Attempting to upsert env var for project ${projectId}`);
// This call succeeds on the server but fails in the SDK's response validation
const result = await vercel.projects.createProjectEnv({
idOrName: projectId,
teamId: process.env.VERCEL_TEAM_ID,
upsert: 'true', // Key for reproduction
requestBody: [
{
key: envKey,
value: envValue,
type: 'encrypted',
target: ['development', 'preview', 'production'],
},
],
});
console.log("SDK call was successful:", result);
} catch (error) {
console.error("SDK call failed:", error);
}
}
// To run:
// upsertAndDeploy('prj_YourProjectId', 'MY_KEY', 'MY_VALUE');Expected Behavior
The createProjectEnv method should successfully parse the HTTP 201 response from the Vercel API and return the result object to the application without throwing an error.
Actual Behavior
The method throws a ResponseValidationError and crashes the application, despite the underlying API call having been successful. The error logs clearly show a ZodError as the root cause.
Key Error Log Snippet:
{
"name": "ResponseValidationError",
"cause": {
"name": "ZodError",
"issues": [
{
"code": "invalid_union",
"unionErrors": [
{
"issues": [
{
"code": "invalid_type",
"expected": "object",
"received": "array",
"path": ["created"],
"message": "Expected object, received array"
}
],
"name": "ZodError"
},
{
"issues": [
{
"code": "invalid_type",
"expected": "array",
"received": "null",
"path": ["created", 0, "customEnvironmentIds"],
"message": "Expected array, received null"
}
],
"name": "ZodError"
}
],
"path": ["created"],
"message": "Invalid input"
}
]
},
"message": "Response validation failed"
}Analysis and Root Cause
The Vercel API for POST /v10/projects/{idOrName}/env has likely been updated. Its successful response payload now contains:
- A
createdfield that is an array of objects. - A
customEnvironmentIdsfield within those objects that can benull.
The @vercel/sdk@1.8.1 still expects the created field to be a single object and the customEnvironmentIds field to be an array. This mismatch causes the SDK's Zod schema to fail validation on a perfectly valid success response.
Suggested Temporary Workaround
For other developers facing this issue, the only current workaround is to bypass the SDK for this specific operation and use a direct fetch call to the API endpoint, which avoids the broken response validation.
// Example Workaround
const response = await fetch(
`https://api.vercel.com/v10/projects/${projectId}/env?upsert=true`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.VERCEL_API_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify([
{ key: 'MY_KEY', value: 'MY_VALUE', type: 'encrypted', target: ['production'] }
])
}
);
if (!response.ok) {
// Handle error
}
const data = await response.json();
console.log('Success:', data);