From 5aab432e5ab5f9f8905943180f9b350e33073b7d Mon Sep 17 00:00:00 2001 From: Nora Date: Fri, 3 Jul 2026 16:53:49 -0600 Subject: [PATCH] fix(smartsheet): handle POST /rows response as either object or array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Smartsheet's POST /sheets/{id}/rows response shape varies by request size: - Single-row request → result: { id, rowNumber, ... } (object) - Multi-row request → result: [{ id, rowNumber, ... }] (array) We always post exactly one row, so the actual response is the object form. The previous fix (b061cdd) assumed the array form, so data.result[0] was undefined for object responses, and addRow threw a 502 'returned no row' AFTER Smartsheet had successfully created the row. The queue then recorded a failed sync attempt even though the data was sitting in the sheet. User saw this in Recent Activity: 10 sequential retries with 'Smartsheet 502: returned no row' errors but incrementing rowNumber in the response body (21 → 30), proving the rows were being created on Smartsheet's side and our parser was the only thing failing. Fix: check Array.isArray(result) and use result[0] for the array form, or result directly for the object form. Belt-and-suspenders for both shapes since Smartsheet's docs are ambiguous about the single-row case. Side note: the failed attempts did create rows on Smartsheet. Once the fix deploys, retries will hit findRowByColumn first, which will locate those existing rows by Entry ID and skip the duplicate insert. Net result: 25 unique rows in the sheet, queue marked synced. --- src/lib/smartsheet.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lib/smartsheet.ts b/src/lib/smartsheet.ts index 9cacc05..f973095 100644 --- a/src/lib/smartsheet.ts +++ b/src/lib/smartsheet.ts @@ -279,12 +279,16 @@ export async function addRow( return v; }; - // NOTE: POST /2.0/sheets/{id}/rows wraps the created row(s) in - // `{ result: [{id, rowNumber}, ...] }` — different shape from the - // flat GET /2.0/sheets/{id} response. See - // https://smartsheet.redoc.ly/#operation/addRows + // NOTE: POST /2.0/sheets/{id}/rows response shape varies: + // - One row in request → result: { id, rowNumber, ... } (single object) + // - Multiple rows → result: [{ id, rowNumber, ... }, ...] (array) + // We always post exactly one row, but handle both defensively. Different + // from the flat GET /2.0/sheets/{id} response. + // See https://smartsheet.redoc.ly/#operation/addRows type ApiResponse = { - result: Array<{ id: number; rowNumber: number }>; + result: + | { id: number; rowNumber: number; [k: string]: unknown } + | Array<{ id: number; rowNumber: number; [k: string]: unknown }>; resultCode?: number; message?: string; }; @@ -305,7 +309,8 @@ export async function addRow( }, ); - const row = data?.result?.[0]; + const result = data?.result; + const row = Array.isArray(result) ? result[0] : result; if (!row || row.id == null) { throw new SmartsheetApiError( 502,