fix: handle invalid session replay config JSON#3561
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
packages/browser/src/extensions/replay/session-recording.ts:278
The object-type guard here uses `typeof persistedConfig === 'object'`, while the equivalent block in `lazy-loaded-session-recorder.ts` uses `isObject(persistedConfig)`. These two checks differ in behaviour for `null` (which passes `typeof === 'object'` but not `isObject`). While both sites guard against `null` via the earlier `!persistedConfig` check, the inconsistency makes the intent harder to follow and could silently diverge if the guard is copied elsewhere. Both sites should use the same helper.
```suggestion
config = isObject(persistedConfig) ? persistedConfig : JSON.parse(persistedConfig)
```
### Issue 2 of 2
packages/browser/src/extensions/replay/session-recording.ts:276-284
**Duplicated safe-parse logic across two files**
The try/catch block here — including its body, the identical comment, and the identical `logger.warn` message — is copy-pasted verbatim into `lazy-loaded-session-recorder.ts` (`_remoteConfig` getter, same shape). This violates OnceAndOnlyOnce. A small shared helper such as `parsePersistedReplayConfig(raw): SessionRecordingPersistedConfig | null` that returns `null` on parse failure would let both callers handle the error uniformly and remove the duplicated comment explaining why mutation is skipped.
Reviews (1): Last reviewed commit: "fix: handle invalid queued replay config..." | Re-trigger Greptile |
| const config = typeof persistedConfig === 'object' ? persistedConfig : JSON.parse(persistedConfig) | ||
| let config: SessionRecordingPersistedConfig | ||
| try { | ||
| config = typeof persistedConfig === 'object' ? persistedConfig : JSON.parse(persistedConfig) |
There was a problem hiding this comment.
The object-type guard here uses
typeof persistedConfig === 'object', while the equivalent block in lazy-loaded-session-recorder.ts uses isObject(persistedConfig). These two checks differ in behaviour for null (which passes typeof === 'object' but not isObject). While both sites guard against null via the earlier !persistedConfig check, the inconsistency makes the intent harder to follow and could silently diverge if the guard is copied elsewhere. Both sites should use the same helper.
| config = typeof persistedConfig === 'object' ? persistedConfig : JSON.parse(persistedConfig) | |
| config = isObject(persistedConfig) ? persistedConfig : JSON.parse(persistedConfig) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/browser/src/extensions/replay/session-recording.ts
Line: 278
Comment:
The object-type guard here uses `typeof persistedConfig === 'object'`, while the equivalent block in `lazy-loaded-session-recorder.ts` uses `isObject(persistedConfig)`. These two checks differ in behaviour for `null` (which passes `typeof === 'object'` but not `isObject`). While both sites guard against `null` via the earlier `!persistedConfig` check, the inconsistency makes the intent harder to follow and could silently diverge if the guard is copied elsewhere. Both sites should use the same helper.
```suggestion
config = isObject(persistedConfig) ? persistedConfig : JSON.parse(persistedConfig)
```
How can I resolve this? If you propose a fix, please make it concise.| let config: SessionRecordingPersistedConfig | ||
| try { | ||
| config = typeof persistedConfig === 'object' ? persistedConfig : JSON.parse(persistedConfig) | ||
| } catch (e) { | ||
| // Do not unregister here: the SDK only registers structured configs, and this read path should | ||
| // ignore corrupt legacy/external values without mutating persistence. | ||
| logger.warn('persisted remote config for session recording is invalid and will be ignored', e) | ||
| return false | ||
| } |
There was a problem hiding this comment.
Duplicated safe-parse logic across two files
The try/catch block here — including its body, the identical comment, and the identical logger.warn message — is copy-pasted verbatim into lazy-loaded-session-recorder.ts (_remoteConfig getter, same shape). This violates OnceAndOnlyOnce. A small shared helper such as parsePersistedReplayConfig(raw): SessionRecordingPersistedConfig | null that returns null on parse failure would let both callers handle the error uniformly and remove the duplicated comment explaining why mutation is skipped.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/browser/src/extensions/replay/session-recording.ts
Line: 276-284
Comment:
**Duplicated safe-parse logic across two files**
The try/catch block here — including its body, the identical comment, and the identical `logger.warn` message — is copy-pasted verbatim into `lazy-loaded-session-recorder.ts` (`_remoteConfig` getter, same shape). This violates OnceAndOnlyOnce. A small shared helper such as `parsePersistedReplayConfig(raw): SessionRecordingPersistedConfig | null` that returns `null` on parse failure would let both callers handle the error uniformly and remove the duplicated comment explaining why mutation is skipped.
How can I resolve this? If you propose a fix, please make it concise.|
Size Change: +3.46 kB (+0.02%) Total Size: 15.9 MB
ℹ️ View Unchanged
|
Problem
Invalid JSON in persisted session replay config, or in a queued snippet call executed during SDK startup, can throw and interrupt PostHog initialization/queued call processing instead of failing gracefully.
Closes #3540
Changes
_execute_arrayso one bad queued call does not abort later queued calls.Release info Sub-libraries affected
Libraries affected
Checklist
If releasing new changes
pnpm changesetto generate a changeset file