diff --git a/apps/worker/src/jobs/library-sync.test.ts b/apps/worker/src/jobs/library-sync.test.ts index 552fe3d..8b377a3 100644 --- a/apps/worker/src/jobs/library-sync.test.ts +++ b/apps/worker/src/jobs/library-sync.test.ts @@ -12,6 +12,10 @@ describe('library sync failure sanitisation', () => { [new PlexConnectionError('UNAUTHENTICATED', 'Plex rejected the supplied token.'), 'authentication', false], [new PlexConnectionError('INVALID_RESPONSE', 'Plex returned an unreadable response.'), 'upstream_response', true], ['token=secret-value', 'unknown', true], + // A body that is not JSON is an odd answer from the server, not a rejected login. + [new SyntaxError('Unexpected token < in JSON at position 0'), 'upstream_response', true], + // A failed database write mentioning a token is not a Plex authentication failure. + [new Error('invalid input syntax for type uuid: bad token'), 'unknown', true], ] as const)('persists only stable safe details for %s', (error, classification, retryable) => { const failure = sanitiseSyncFailure(error) diff --git a/apps/worker/src/jobs/library-sync.ts b/apps/worker/src/jobs/library-sync.ts index 0da15e0..877dc57 100644 --- a/apps/worker/src/jobs/library-sync.ts +++ b/apps/worker/src/jobs/library-sync.ts @@ -84,12 +84,16 @@ export function sanitiseSyncFailure(error: unknown): SanitisedSyncFailure { } return { classification: 'upstream_response', summary: 'Plex returned an unexpected response.', retryable: true } } + // A body that is not JSON is an unexpected answer from the server, not a rejected login. + if (error instanceof SyntaxError) { + return { classification: 'upstream_response', summary: 'Plex returned an unexpected response.', retryable: true } + } const message = error instanceof Error ? error.message.toLowerCase() : '' if (message.includes('encryption') || message.includes('configuration') || message.includes('required before')) { return { classification: 'configuration', summary: 'Sync configuration needs attention.', retryable: false } } - if (message.includes('unauthor') || message.includes('forbidden') || message.includes('credential') || message.includes('token')) { + if (message.includes('unauthor') || message.includes('forbidden') || message.includes('credential') || (message.includes('plex') && message.includes('token'))) { return { classification: 'authentication', summary: 'Plex authentication was rejected.', retryable: false } } if (message.includes('timeout') || message.includes('network') || message.includes('connect') || message.includes('unavailable')) {