Driftwatch

Vercel / Vercel REST API /

Breakingdirection flip: their tools call this safe

nodeVersion can now return "26.x"

What changed

Producer-side tools call this additive. It breaks exhaustive switches, strict parsers and generated client enums.

Affects nodeVersion on POST /v1/projects/{idOrName}/avatar.

New value: 26.x.

can now return "26.x"

Who is affected

Code that reads POST /v1/projects/{idOrName}/avatar (nodeVersion).

Before and after

WhereBeforeAfter
POST /v1/projects/{idOrName}/avatar · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
GET /v1/microfrontends/groups/{groupId}/projects · projects[].nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
DELETE /v1/projects/{idOrName}/avatar · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
PATCH /v1/projects/{projectId}/microfrontends · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
GET /v10/projects · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
GET /v10/projects · projects[].nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
POST /v11/projects · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
PATCH /v12/deployments/{id}/cancel · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
PATCH /v12/deployments/{id}/cancel · projectSettings.nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
POST /v13/deployments · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
POST /v13/deployments · projectSettings.nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
GET /v13/deployments/{idOrUrl} · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
GET /v13/deployments/{idOrUrl} · projectSettings.nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
GET /v7/deployments · deployments[].projectSettings.nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
GET /v9/projects/{idOrName} · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"
PATCH /v9/projects/{idOrName} · nodeVersion"10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "8.10.x""10.x", "12.x", "14.x", "16.x", "18.x", "20.x", "22.x", "24.x", "26.x", "8.10.x"

Code that breaks

switch (response.nodeVersion) {
  // existing branches …
  // no branch for "26.x"
  default:
    throw new Error("unexpected nodeVersion");
}

Based on Vercel’s published API specification. How severity is decided.