Game Engine Issues May 7, 2026 12 min read

OpenXR Startup Selection Telemetry Missing on Quest Build - Instrumentation Order and Route Trace Fix

Fix Unity OpenXR Quest builds that launch with missing startup selection telemetry by enforcing instrumentation order, route ownership tracing, fallback logging, and candidate-level verification.

By GamineAI Team

OpenXR Startup Selection Telemetry Missing on Quest Build - Instrumentation Order and Route Trace Fix

If your Unity OpenXR project runs on Quest but your startup logs do not show which input route was selected, your release risk is much higher than it looks.

In 2026 this issue spikes because mixed-input Quest projects (controllers, hands, eye-gaze fallback paths) are now commonly shipped with stricter release evidence requirements. Teams can no longer rely on "it felt correct in smoke test." You need deterministic startup evidence.

Problem

Editor tests pass, Quest build launches, interaction appears mostly functional, but startup telemetry is missing or unusable:

  • no selected profile row
  • no fallback index
  • no selection reason
  • no stable candidate identifier in logs

This creates audit and promotion blockers because no one can prove why startup chose one route over another.

Fastest safe fix path

  1. Lock one startup owner and one telemetry contract per candidate.
  2. Emit startup telemetry before first gameplay route activation.
  3. Log ordered milestones for primary attempt, fallback step, and final selection.
  4. Run clean-install and warm-install replay checks on Quest.
  5. Block promotion when required telemetry fields are missing.

If you do only one thing today, do this: enforce required field presence as a hard gate, not a warning.

Why this happens

Most missing-telemetry cases are not caused by OpenXR itself. They come from release-lane drift:

  • instrumentation runs too late (after route already switched)
  • multiple startup owners overwrite route state
  • fallback logic emits generic "success" without decision details
  • one scene logs telemetry while another scene owns startup logic
  • build candidate identity is not injected into log rows

You can fix this without rewriting your input stack if you standardize route instrumentation order.

Required telemetry contract (minimum fields)

Before you debug, define required fields:

  1. candidate_id
  2. profile_contract_id
  3. startup_scene_id
  4. primary_route_attempt
  5. fallback_step_index
  6. selected_route
  7. selection_reason
  8. selection_latency_ms
  9. route_owner_id
  10. permission_state_snapshot

Any startup run missing one of these should be marked invalid for release decisioning.

Step-by-step fix

1) Freeze startup ownership

Choose one startup owner component that:

  • loads route contract
  • evaluates primary route readiness
  • runs fallback logic
  • emits all telemetry milestones

Disable or remove duplicate startup controllers in bootstrap and additive scenes.

Verification checkpoint: exactly one owner ID appears in startup logs.

2) Move telemetry emission earlier in startup

Common mistake: writing logs only after route activation. By then, early branches are already lost.

Emit these rows in order:

  1. contract_loaded
  2. primary_attempt_started
  3. primary_attempt_result
  4. fallback_attempt_started (if needed)
  5. fallback_attempt_result (if needed)
  6. final_route_selected

Do not collapse them into one "startup done" message.

Verification checkpoint: all milestone rows appear in consistent order for each run.

3) Instrument fallback with explicit index values

Fallback logging must include numeric route sequence:

  • fallback_step_index = 0 for first alternative
  • increment for each additional fallback branch

Avoid text-only labels like "fallback happened." They are not replay-safe.

Verification checkpoint: fallback step values are contiguous and never skip unexpectedly.

4) Attach stable candidate identity

Inject candidate metadata into startup logs:

  • build identifier
  • commit hash or artifact hash
  • packet revision

Without this, two runs from different builds can be mixed and produce false pass signals.

Verification checkpoint: every startup row includes the same candidate tuple.

5) Capture permission snapshot at decision time

Quest startup route can depend on runtime permission or capability state. If permission status is not captured when selection happens, logs become misleading.

Record at decision time:

  • permission requested yes/no
  • permission granted yes/no
  • profile capability enabled yes/no

Verification checkpoint: permission snapshot exists before final route selection row.

6) Run clean-install and warm-install route replay

Execute two required scenarios on Quest:

  • clean install startup
  • warm startup after prior run

Some teams only test warm runs and miss first-launch route failures.

Verification checkpoint: both scenarios produce complete telemetry rows with matching field schema.

7) Add release no-go telemetry gate

Create a gate that fails when:

  • any required field is null
  • milestone order is invalid
  • fallback index is missing during fallback
  • selected route has no selection reason

Mark this as hard hold in release workflow.

Verification checkpoint: gate result is recorded with pass/fail and reason code.

Practical diagnostic flow (10-15 minutes)

Use this sequence when support reports missing startup logs:

  1. confirm one startup owner in active scene graph
  2. run Quest build and collect first-launch logs
  3. check required field presence
  4. check milestone ordering
  5. check fallback index continuity
  6. check candidate ID consistency
  7. classify issue and patch

This keeps troubleshooting deterministic instead of speculative.

Root-cause matrix

Symptom Likely cause Fast fix
final selected route exists but no attempt rows instrumentation starts too late emit rows before route activation
startup logs appear in editor but not Quest platform-conditional logging path move telemetry to platform-neutral startup owner
fallback route selected but no fallback index incomplete fallback logger add numeric step index to each branch
mixed candidate IDs in one run stale build metadata injection bind candidate tuple at process start
generic reason code for all routes reason mapping not wired to branch outcomes map explicit reason per branch and failure type

Alternative fixes for stubborn cases

If standard instrumentation still fails, try these branches:

Branch A: Scene lifecycle race

Symptom: telemetry rows appear randomly between runs.

Fix:

  • move owner initialization to earliest deterministic lifecycle point
  • block dependent route activators until contract load event confirms

Branch B: Multiple package versions or stale assemblies

Symptom: logger callbacks compile but do not fire in device build.

Fix:

  • verify package parity across CI and local builds
  • clear stale build artifacts and rebuild candidate

Branch C: Log transport truncation

Symptom: expected rows emitted locally but truncated in captured output.

Fix:

  • reduce noisy startup logs
  • ensure route logs use stable structured prefix for extraction

Verification checklist before promotion

A candidate is ready only if all checks pass:

  1. required telemetry fields complete in all startup scenarios
  2. milestone order deterministic across replay runs
  3. fallback index continuity verified
  4. selection reason present and branch-specific
  5. candidate ID tuple consistent in all startup rows
  6. release gate recorded as pass

If one fails, hold and patch. Do not ship with "partially readable" startup telemetry.

Escalation criteria for release owners

If startup telemetry remains incomplete after one patch attempt, escalate using explicit criteria instead of open-ended retries.

Escalate to release hold review when:

  • two consecutive Quest replay runs still miss required fields
  • startup owner identity changes between identical candidate runs
  • fallback index continuity fails in clean-install scenario
  • candidate tuple values differ across rows from one startup attempt

Escalation packet should include:

  • candidate id and artifact hash
  • failing checkpoint IDs
  • last known good candidate for comparison
  • owner assignment and next decision checkpoint time

This prevents ambiguous "still investigating" states during launch windows.

Prevention pattern for future releases

Use these release habits:

  • keep telemetry contract versioned with route contract
  • keep one owner-of-truth for startup routing
  • run two-scenario replay check in CI candidate validation
  • add trend alert when missing-field rate rises above threshold

This turns startup telemetry from a one-time debug task into routine release hygiene.

Common mistakes to avoid

Mistake: Treating telemetry as optional debug output

Fix: classify startup telemetry as release evidence, not developer convenience.

Mistake: Logging only final selected route

Fix: log ordered decision milestones and branch reasons.

Mistake: Allowing scene-level startup owners to drift

Fix: enforce one startup owner and explicit ownership checks in smoke test.

Mistake: Not binding candidate metadata

Fix: inject candidate tuple once and stamp every startup row.

FAQ

Do we need this if the game works on Quest already

Yes. Functionality without route evidence is fragile. Missing telemetry prevents reliable regression diagnosis and slows release decisions.

Is this only for hand-tracking projects

No. Any project with multiple possible startup routes can be affected, including controller-primary flows with fallback branches.

Should missing telemetry be warning or hard fail

For release candidates it should be hard fail. If route evidence is incomplete, promotion confidence is incomplete.

Can we patch telemetry after submission

Technically yes, but that usually increases cycle time and obscures incident timelines. Fix before promotion whenever possible.

Related problems and links

Official references: Unity OpenXR documentation and Khronos OpenXR specification.

Bookmark this fix for your next Quest candidate review. Share it with teammates who own startup route validation.