Summary
Reported externally (Leia, medium): on a dev box with a checked-out repo, workspace mode auto-resolves a stale *-dev.json manifest and forces it as XR_RUNTIME_JSON for child apps, overriding the installed runtime. Child apps then die with XR_ERROR_RUNTIME_UNAVAILABLE / XR_ERROR_RUNTIME_FAILURE. End-users never hit it (no repo on disk); every dev does. Reporter's workaround: rename the dev manifest to .disabled.
Where this lives
The reporter saw the shell scan a hard-coded C:\openxr-3d-display\build\Release\openxr_displayxr-dev.json — note that's the pre-rename repo path (it's been displayxr-runtime since the May de-privatize), i.e. a stale one-developer convenience hack baked into the shipped shell. That instance is shell-side (displayxr-shell-pvt) and needs its own counterpart issue.
But this repo carries the same class of footgun in the Ctrl+O "Launch App in Workspace" path:
src/xrt/compositor/d3d11/comp_d3d11_window.cpp:998-1018
SetEnvironmentVariableA("DISPLAYXR_WORKSPACE_SESSION", "1");
if (getenv("XR_RUNTIME_JSON") == NULL) {
// _package/bin/../../build/Release/openxr_displayxr-dev.json
snprintf(json_path, ..., "%s\\..\\..\\build\\Release\\openxr_displayxr-dev.json", module_dir);
if (_fullpath(...) && GetFileAttributesA(abs_json) != INVALID_FILE_ATTRIBUTES) {
SetEnvironmentVariableA("XR_RUNTIME_JSON", abs_json); // forces dev runtime onto children
}
}
This one is milder than the shell's (it's module-relative, and gated on XR_RUNTIME_JSON being unset), but it still silently injects a dev manifest into child apps purely because a build/Release/ tree happens to exist next to the binary — exactly the dev-box failure the reporter describes.
Fix
Dev-manifest resolution should be explicit opt-in, never auto-detected from disk:
- Gate behind an explicit env var (e.g.
DISPLAYXR_DEV=1) or CLI flag — do not auto-resolve *-dev.json from a sibling build/ tree.
- Preferably: in a shipped/installed context the runtime should never override
XR_RUNTIME_JSON for children — let the Khronos loader resolve the installed runtime via HKLM\...\OpenXR\1\ActiveRuntime, exactly as an end-user box does.
- If dev-manifest support stays, validate the manifest points to a compatible runtime version before honoring it (otherwise we trade a silent stale-runtime for a silent wrong-version).
Cross-refs
- Reporter's exact instance (hard-coded
C:\openxr-3d-display path) is shell-side → needs a displayxr-shell-pvt counterpart.
Summary
Reported externally (Leia, medium): on a dev box with a checked-out repo, workspace mode auto-resolves a stale
*-dev.jsonmanifest and forces it asXR_RUNTIME_JSONfor child apps, overriding the installed runtime. Child apps then die withXR_ERROR_RUNTIME_UNAVAILABLE/XR_ERROR_RUNTIME_FAILURE. End-users never hit it (no repo on disk); every dev does. Reporter's workaround: rename the dev manifest to.disabled.Where this lives
The reporter saw the shell scan a hard-coded
C:\openxr-3d-display\build\Release\openxr_displayxr-dev.json— note that's the pre-rename repo path (it's beendisplayxr-runtimesince the May de-privatize), i.e. a stale one-developer convenience hack baked into the shipped shell. That instance is shell-side (displayxr-shell-pvt) and needs its own counterpart issue.But this repo carries the same class of footgun in the Ctrl+O "Launch App in Workspace" path:
src/xrt/compositor/d3d11/comp_d3d11_window.cpp:998-1018This one is milder than the shell's (it's module-relative, and gated on
XR_RUNTIME_JSONbeing unset), but it still silently injects a dev manifest into child apps purely because abuild/Release/tree happens to exist next to the binary — exactly the dev-box failure the reporter describes.Fix
Dev-manifest resolution should be explicit opt-in, never auto-detected from disk:
DISPLAYXR_DEV=1) or CLI flag — do not auto-resolve*-dev.jsonfrom a siblingbuild/tree.XR_RUNTIME_JSONfor children — let the Khronos loader resolve the installed runtime viaHKLM\...\OpenXR\1\ActiveRuntime, exactly as an end-user box does.Cross-refs
C:\openxr-3d-displaypath) is shell-side → needs a displayxr-shell-pvt counterpart.