From a7dfeedcddb907ba715da051a7350d3d68316f9c Mon Sep 17 00:00:00 2001 From: Eddie Yu Date: Fri, 14 Aug 2026 10:10:49 +0800 Subject: [PATCH 1/2] fix(client): don't let non-JSON error bodies crash requests FAMIS can return a 5xx with a plain-text body (e.g. "Service Unavailable" on a 503). Axios's default transformResponse could throw a raw SyntaxError trying to JSON.parse that body, which skipped throwResponseError entirely and surfaced an unhandled parse error instead of a clean ApiError with the real status. The shared axios instance now parses defensively and falls back to the raw string. Fixes #458 Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 8 ++++++++ famis_client.ts | 18 ++++++++++++++++++ package.json | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff0adf0..4d8245b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 > Entries before 1.2.0 were not tracked in this file; see the git history for details. +## [Unreleased] +### Fixed +- Non-JSON error bodies (e.g. a plain-text `"Service Unavailable"` on a FAMIS 503) no + longer crash requests with a raw `SyntaxError`/`"... is not valid JSON"`. The shared + axios instance now parses defensively and falls back to the raw string, so + `throwResponseError`/`ApiError` always get a real response to work with instead of + axios's transform throwing before one exists. (#458) + ## [1.4.0] — 2026-07-17 ### Added - Opt-in **keyset (Id-range-partitioned) parallel paging** for the assets batch fetch. diff --git a/famis_client.ts b/famis_client.ts index 7404fcd..ea3e1c1 100644 --- a/famis_client.ts +++ b/famis_client.ts @@ -387,6 +387,24 @@ export class FamisClient { // socket, freeing the slot) instead of hanging forever. Per-request, not // per-operation — safe for paginated fetches (each page is its own request). timeout: requestTimeoutMs, + // FAMIS sometimes returns a non-JSON body (e.g. plain-text "Service Unavailable") + // on 5xx errors. Axios's default transformResponse can throw a raw SyntaxError in + // that case instead of resolving, which skips throwResponseError entirely and + // surfaces an unhandled parse error instead of a clean ApiError with the real + // status. Parse defensively and fall back to the raw string so every request + // resolves to a normal AxiosResponse. + transformResponse: [ + (data: any) => { + if (typeof data === 'string' && data.length) { + try { + return JSON.parse(data); + } catch (e) { + return data; + } + } + return data; + }, + ], }); if (autoRetry) { const RETRIES = 6; diff --git a/package.json b/package.json index 89ec2aa..a113baf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "facility360", - "version": "1.4.0", + "version": "1.4.1", "description": "A Node based 360Facility client SDK", "main": "dist/index.js", "files": [ From c5dc250dc7e3efe35accf8aa554b636b619187a3 Mon Sep 17 00:00:00 2001 From: Eddie Yu Date: Fri, 14 Aug 2026 10:11:17 +0800 Subject: [PATCH 2/2] docs(changelog): move 1.4.1 fix entry out of Unreleased Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8245b..a06b0c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 > Entries before 1.2.0 were not tracked in this file; see the git history for details. -## [Unreleased] +## [1.4.1] — 2026-08-14 ### Fixed - Non-JSON error bodies (e.g. a plain-text `"Service Unavailable"` on a FAMIS 503) no longer crash requests with a raw `SyntaxError`/`"... is not valid JSON"`. The shared