From 29cf3e7d9f5f5ad50affc2770cc2f0a1b14e72ea Mon Sep 17 00:00:00 2001 From: Waleed Date: Sat, 11 Jul 2026 22:10:16 -0700 Subject: [PATCH] fix(ashby): fail loudly instead of silently dropping malformed socialLinks (#5624) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(ashby): fail loudly instead of silently dropping malformed socialLinks parseSocialLinksInput returned [] for any non-JSON-parseable input, and tools.config.params only sets result.socialLinks when the parsed array is non-empty — so a malformed socialLinks string (user typo, or a wand response that didn't follow the JSON-array prompt) silently omitted the field entirely. The Ashby candidate.update call then succeeded without applying the requested links, with no error surfaced to the workflow author. Throw a clear error instead, matching the existing throw-on-invalid-JSON pattern used elsewhere (e.g. blocks/airtable.ts). * fix(ashby): use getErrorMessage instead of inline error-message extraction check:utils bans the e instanceof Error ? e.message : fallback pattern in favor of getErrorMessage(e, fallback?) from @sim/utils/errors. --- apps/sim/blocks/blocks/ashby.test.ts | 21 ++++++++++++++++----- apps/sim/blocks/blocks/ashby.ts | 17 +++++++++++++---- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/apps/sim/blocks/blocks/ashby.test.ts b/apps/sim/blocks/blocks/ashby.test.ts index 75a26b13b6..748efee159 100644 --- a/apps/sim/blocks/blocks/ashby.test.ts +++ b/apps/sim/blocks/blocks/ashby.test.ts @@ -47,11 +47,22 @@ describe('AshbyBlock', () => { expect(result.socialLinks).toEqual([{ type: 'Twitter', url: 'https://twitter.com/jane' }]) }) - it('omits the field when the JSON is malformed', () => { - const result = AshbyBlock.tools.config.params!( - buildParams('update_candidate', { socialLinks: 'not json' }) - ) - expect(result.socialLinks).toBeUndefined() + it('throws instead of silently dropping the field when the JSON is malformed', () => { + // A silent [] here would let the Ashby update proceed without applying + // the requested links and with no error shown to the workflow author. + expect(() => + AshbyBlock.tools.config.params!( + buildParams('update_candidate', { socialLinks: 'not json' }) + ) + ).toThrow(/Invalid JSON in Ashby social links/) + }) + + it('throws when the parsed JSON is not an array', () => { + expect(() => + AshbyBlock.tools.config.params!( + buildParams('update_candidate', { socialLinks: '{"type":"Twitter"}' }) + ) + ).toThrow(/expected a JSON array/) }) }) diff --git a/apps/sim/blocks/blocks/ashby.ts b/apps/sim/blocks/blocks/ashby.ts index 78c63efee3..06fcf15752 100644 --- a/apps/sim/blocks/blocks/ashby.ts +++ b/apps/sim/blocks/blocks/ashby.ts @@ -1,3 +1,4 @@ +import { getErrorMessage } from '@sim/utils/errors' import { AshbyIcon } from '@/components/icons' import { AuthMode, type BlockConfig, type BlockMeta, IntegrationType } from '@/blocks/types' import { getTrigger } from '@/triggers' @@ -22,12 +23,20 @@ function parseStringListInput(value: unknown): string[] { function parseSocialLinksInput(value: unknown): Array<{ type: string; url: string }> { if (Array.isArray(value)) return value as Array<{ type: string; url: string }> if (typeof value !== 'string' || !value.trim()) return [] + let parsed: unknown try { - const parsed = JSON.parse(value) - return Array.isArray(parsed) ? parsed : [] - } catch { - return [] + parsed = JSON.parse(value) + } catch (error) { + throw new Error( + `Invalid JSON in Ashby social links: ${getErrorMessage(error)}. Expected a JSON array like [{"type":"Twitter","url":"https://twitter.com/x"}].` + ) } + if (!Array.isArray(parsed)) { + throw new Error( + 'Invalid Ashby social links: expected a JSON array like [{"type":"Twitter","url":"https://twitter.com/x"}].' + ) + } + return parsed } export const AshbyBlock: BlockConfig = {