Skip to content

fix: warn about off-main view layout in debug mode - #815

Merged
marandaneto merged 1 commit into
mainfrom
fix/issue-806-layout-warning
Sep 10, 2026
Merged

fix: warn about off-main view layout in debug mode#815
marandaneto merged 1 commit into
mainfrom
fix/issue-806-layout-warning

Conversation

@marandaneto

@marandaneto marandaneto commented Sep 10, 2026

Copy link
Copy Markdown
Member

💡 Motivation and Context

Related to #806. The layout hook forwards to UIKit before notifying PostHog, so an exception in UIKit can occur before the existing notification thread check. The investigation reproduced the crash path with and without the hook. The customer's production trigger remains unproven.

This adds a debug-gated warning before forwarding an off-main layout call. A dedicated lock makes the warning once per process. Calls while debug logging is disabled do not consume it, and restarting the layout subscription does not reset it.

UIKit forwarding remains synchronous on the calling thread. PostHog notifications still run on main. There is no layout suppression, new public option, or scheduler redesign. The lifecycle reproductions in #814 and the architecture proposal in #813 remain separate work.

💚 How did you test it?

  • Added regression tests for main/background forwarding, view and layer identity, main-thread callback delivery, debug gating, warning order, concurrent once-only logging, and subscription restarts. The tests replace only a test view's call-through, not UIKit layout for other views.
  • Verified the warning test failed against the original SDK because no warning was emitted.
  • The focused iOS suite passes under Thread Sanitizer with three repetitions on iOS 26.5. The new subscriptions use replay's trailing delivery. The polling helper now runs on main to avoid reading callback counters concurrently.
  • make test, make format, and make lint pass after syncing with main.
  • make build passes all SDK platforms and platform examples, then fails in the external-SDK client example because its package reference assumes the checkout directory is named posthog-ios. The worktree is named posthog-ios-issue-806. CocoaPods examples were not reached.
  • Isolated autoreview against origin/main passed for 88a4f5d0cfd80df9bf3d1c2bf9333aea8338d58f with no actionable findings.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed. No public API change.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran pnpm changeset to generate a changeset file. A patch changeset was added directly.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Manoel directed the scope. Pi used file read/edit tools, shell commands, GitHub CLI, make-based validation, and isolated Pi autoreview. Investigation details are in #806.

The chosen change is diagnostic only. We explicitly rejected changing UIKit layout timing, adding a suppression flag, or claiming that the SDK's presence in the crash stack proves causation. A separate draft contains the lifecycle reproductions. Human review is required.

@marandaneto marandaneto self-assigned this Sep 10, 2026
@marandaneto
marandaneto marked this pull request as ready for review September 10, 2026 07:54
@marandaneto
marandaneto requested a review from a team as a code owner September 10, 2026 07:54
@greptile-apps

greptile-apps Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "fix: warn about off-main view layout in ..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown
Contributor

posthog-ios Compliance Report

Date: 2026-09-10 08:10:31 UTC
Duration: 240028ms

✅ All Tests Passed!

45/45 tests passed


Capture Tests

29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields 2901ms
Format Validation.Event Has Uuid 2880ms
Format Validation.Event Has Lib Properties 2866ms
Format Validation.Distinct Id Is String 2892ms
Format Validation.Token Is Present 2782ms
Format Validation.Custom Properties Preserved 3049ms
Format Validation.Event Has Timestamp 800ms
Retry Behavior.Retries On 503 11853ms
Retry Behavior.Does Not Retry On 400 5015ms
Retry Behavior.Does Not Retry On 401 4887ms
Retry Behavior.Respects Retry After Header 7769ms
Retry Behavior.Implements Backoff 21840ms
Retry Behavior.Retries On 500 9385ms
Retry Behavior.Retries On 502 9358ms
Retry Behavior.Retries On 504 9300ms
Retry Behavior.Max Retries Respected 21870ms
Deduplication.Generates Unique Uuids 3299ms
Deduplication.Preserves Uuid On Retry 9365ms
Deduplication.Preserves Uuid And Timestamp On Retry 16783ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry 7853ms
Deduplication.No Duplicate Events In Batch 2894ms
Deduplication.Different Events Have Different Uuids 2848ms
Compression.Sends Gzip When Enabled 2857ms
Batch Format.Uses Proper Batch Structure 2827ms
Batch Format.Flush With No Events Sends Nothing 358ms
Batch Format.Multiple Events Batched Together 3036ms
Error Handling.Does Not Retry On 403 4935ms
Error Handling.Does Not Retry On 413 4864ms
Error Handling.Retries On 408 8991ms

Feature_Flags Tests

16/16 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id 3214ms
Request Payload.Flags Request Uses V2 Query Param 3138ms
Request Payload.Flags Request Hits Flags Path Not Decide 2922ms
Request Payload.Flags Request Omits Authorization Header 2971ms
Request Payload.Token In Flags Body Matches Init 3032ms
Request Payload.Groups Round Trip 2912ms
Request Payload.Groups Default To Empty Object 2855ms
Request Payload.Person Properties Distinct Id Auto Populated When Caller Omits It 2977ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False 3175ms
Request Payload.Disable Geoip Omitted Defaults To False 2994ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key 3008ms
Request Lifecycle.No Flags Request On Init Alone 129ms
Request Lifecycle.No Flags Request On Normal Capture 2943ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests 5855ms
Request Lifecycle.Mock Response Value Is Returned To Caller 2989ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event 3248ms

@ioannisj ioannisj left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if warning about misuse of main thread should be this SDK's responsibility tbh. Esp since Main Thread checker is on by default for debug builds? Harmless change though so up to you

@marandaneto

Copy link
Copy Markdown
Member Author

Not sure if warning about misuse of main thread should be this SDK's responsibility tbh. Esp since Main Thread checker is on by default for debug builds? Harmless change though so up to you

only with hedgeLogEnabled enabled and only once, so no harm, helps diagnose #806

@marandaneto
marandaneto merged commit d8c5407 into main Sep 10, 2026
50 checks passed
@marandaneto
marandaneto deleted the fix/issue-806-layout-warning branch September 10, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants