diff --git a/src/shared/remoteSourceTrackingService.ts b/src/shared/remoteSourceTrackingService.ts index 3fdad1ca..ea28d3cd 100644 --- a/src/shared/remoteSourceTrackingService.ts +++ b/src/shared/remoteSourceTrackingService.ts @@ -11,6 +11,7 @@ import { EOL } from 'node:os'; import { retryDecorator, NotRetryableError } from 'ts-retry-promise'; import { Logger, Org, Messages, Lifecycle, SfError, Connection, lockInit } from '@salesforce/core'; import { env, Duration, parseJsonMap } from '@salesforce/kit'; +import { isString } from '@salesforce/ts-types'; import { ChangeResult, RemoteChangeElement, @@ -542,13 +543,19 @@ function getDecodedKeyIfSourceMembersHas({ key: string; logger: Logger; }): string { - const originalKeyDecoded = decodeURIComponent(key); - const match = Array.from(sourceMembers.keys()).find( - (memberKey) => decodeURIComponent(memberKey) === originalKeyDecoded - ); - if (match) { - logger.debug(`${match} matches already tracked member: ${key}`); - return match; + try { + const originalKeyDecoded = decodeURIComponent(key); + const match = Array.from(sourceMembers.keys()).find( + (memberKey) => decodeURIComponent(memberKey) === originalKeyDecoded + ); + if (match) { + logger.debug(`${match} matches already tracked member: ${key}`); + return match; + } + } catch (e: unknown) { + // Log the error and the key + const errMsg = e instanceof Error ? e.message : isString(e) ? e : 'unknown'; + logger.debug(`Could not decode metadata key: ${key} due to: ${errMsg}`); } return key; } diff --git a/test/unit/remoteSourceTracking.test.ts b/test/unit/remoteSourceTracking.test.ts index d03dd12c..0b3d053c 100644 --- a/test/unit/remoteSourceTracking.test.ts +++ b/test/unit/remoteSourceTracking.test.ts @@ -331,6 +331,15 @@ describe('remoteSourceTrackingService', () => { ); }); + it('should not throw for non-decodeable key missing from SourceMember map on get', () => { + // trying to decode '%E0%A4%A' throws a URIError so getDecodedKeyIfSourceMembersHas() + // should not throw when a non-decodeable key is encountered. + const sourceMemberKey = 'Layout__Broker__c-%E0%A4%A'; + + // @ts-ignore getSourceMember is private + expect(remoteSourceTrackingService.getSourceMember(sourceMemberKey)).to.equal(undefined); + }); + it('will match/update encoded SourceMember keys on set', () => { const maxJson = { serverMaxRevisionCounter: 2,