From c1aad8a819df599888f4d76ec6d0712be5ad2c2d Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sun, 31 May 2026 01:50:11 -0700 Subject: [PATCH] fix(tracker-web): do not send Content-Type on bodyless fleet proxy POSTs Operator actions (ship/requeue/cancel) are bodyless POSTs. The proxy always set Content-Type: application/json, so the backend rejected them with FST_ERR_CTP_EMPTY_JSON_BODY (500). Only declare the JSON content type when a body is actually forwarded. Fixes the fleet dashboard action buttons. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../tracker-web/src/app/api/fleet/[...path]/route.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dashboards/tracker-web/src/app/api/fleet/[...path]/route.ts b/dashboards/tracker-web/src/app/api/fleet/[...path]/route.ts index 8d6bc366..9237ccd3 100644 --- a/dashboards/tracker-web/src/app/api/fleet/[...path]/route.ts +++ b/dashboards/tracker-web/src/app/api/fleet/[...path]/route.ts @@ -18,7 +18,7 @@ async function proxy(req: NextRequest, { params }: { params: Promise<{ path: str }); try { - const headers: Record = { 'Content-Type': 'application/json' }; + const headers: Record = {}; const auth = req.headers.get('authorization'); if (auth) headers['Authorization'] = auth; @@ -37,7 +37,13 @@ async function proxy(req: NextRequest, { params }: { params: Promise<{ path: str if (req.method !== 'GET' && req.method !== 'HEAD') { const body = await req.text(); - if (body) fetchOptions.body = body; + if (body) { + fetchOptions.body = body; + // Only declare a JSON body when there actually is one — bodyless POSTs + // (operator actions: ship/requeue/cancel) must NOT send Content-Type, or + // the backend rejects them with FST_ERR_CTP_EMPTY_JSON_BODY. + headers['Content-Type'] = 'application/json'; + } } const res = await fetch(url.toString(), fetchOptions);