fix(ashby): fail loudly instead of silently dropping malformed socialLinks (#5624)

* 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.
This commit is contained in:
Waleed
2026-07-11 22:10:16 -07:00
committed by GitHub
parent b20bbdc111
commit 29cf3e7d9f
2 changed files with 29 additions and 9 deletions
+16 -5
View File
@@ -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/)
})
})
+13 -4
View File
@@ -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 = {