fix: improve Vercel domain 'forbidden' error message and add schema fields (#25520)

* fix: improve Vercel domain 'forbidden' error message

The 'forbidden' error code from Vercel is a generic permission denial,
not specifically 'domain owned by another team'. It can occur for various
reasons: wrong teamId, token lacking project access, account-level
restrictions, or domain ownership by another team.

Updated the error message to be more accurate and changed the HTTP status
code from 400 to 403 to better reflect the permission error nature.

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix: add message and invalidToken fields to Vercel error response schema

This allows better logging of Vercel API error responses, especially when
tokens become invalid. The new fields help with debugging permission issues.

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix: revert status code to 400 for Vercel forbidden errors

Keep the status code at 400 to avoid potential downstream side effects
while still using the improved error message and schema fields.

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix: use .nullish() instead of .optional() for message and invalidToken fields

.nullish() handles both null and undefined, which is safer for API responses.

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Hariom Balhara
2025-12-05 05:26:42 +00:00
committed by GitHub
co-authored by Devin AI
parent 44291be7b7
commit b80c0692dc
@@ -12,6 +12,8 @@ const vercelDomainApiResponseSchema = z.object({
.object({
code: z.string().nullish(),
domain: z.any().nullish(),
message: z.string().nullish(),
invalidToken: z.boolean().nullish(),
})
.optional(),
});
@@ -74,10 +76,16 @@ export const deleteDomain = async (domain: string) => {
return handleDomainDeletionError(data.error);
};
function handleDomainCreationError(error: { code?: string | null; domain?: string | null }) {
// Domain is already owned by another team but you can request delegation to access it
function handleDomainCreationError(error: {
code?: string | null;
domain?: string | null;
message?: string | null;
invalidToken?: boolean | null;
}){
// Vercel returns "forbidden" for various permission issues, not just domain ownership
if (error.code === "forbidden") {
const errorMessage = "Domain is already owned by another team";
const errorMessage =
"Vercel denied permission to manage this domain. Please verify your Vercel project, team, and domain permissions.";
log.error(
safeStringify({
errorMessage,
@@ -117,15 +125,21 @@ function handleDomainCreationError(error: { code?: string | null; domain?: strin
});
}
function handleDomainDeletionError(error: { code?: string | null; domain?: string | null }) {
function handleDomainDeletionError(error: {
code?: string | null;
domain?: string | null;
message?: string | null;
invalidToken?: boolean | null;
}){
if (error.code === "not_found") {
// Domain is already deleted
return true;
}
// Domain is already owned by another team but you can request delegation to access it
// Vercel returns "forbidden" for various permission issues, not just domain ownership
if (error.code === "forbidden") {
const errorMessage = "Domain is owned by another team";
const errorMessage =
"Vercel denied permission to manage this domain. Please verify your Vercel project, team, and domain permissions.";
log.error(
safeStringify({
errorMessage,