Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/wsl/wsl-container-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ MXC, which lets you run Linux containers on Windows using the WSLC SDK.
| Requirement | Details |
|---|---|
| **Windows 11** | Required for WSL2 and the WSLC SDK |
| **WSL 2.9.3+** | See Step 1 below for installation |
| **WSLC SDK** | `wslcsdk.dll` must be in the same directory as `wxc-exec.exe` |
| **Windows 11** | Required for WSL2 and the WSLC SDK |
| **WSL 2.9.3+** | The installed WSL runtime package must meet the WSLC minimum; see Step 1 below for installation |
| **WSLC SDK** | `wslcsdk.dll` is a separate client SDK and must be in the same directory as `wxc-exec.exe` |
| **Container images** | Pre-pulled or available from a registry with network access |

## Step 1 β€” Install WSL 2.9.3+
Expand Down Expand Up @@ -299,7 +300,7 @@ the container.
|---|---|---|
| `WSLC backend not compiled` | Binary built without `--features wslc` | Rebuild with `build.bat --with-wslc` |
| `Failed to load wslcsdk.dll` | DLL not in same directory as `wxc-exec.exe` | Copy `wslcsdk.dll` next to the binary |
| `WSLC runtime not available` | WSL version too old or missing components | Update WSL with `wsl --update` or build from the [WSL repo](https://github.com/microsoft/WSL/tree/feature/wsl-for-apps) |
| `WSLC runtime unavailable` | WSL runtime package is missing, older than 2.9.3, or the Virtual Machine Platform optional component is disabled | Update WSL with `wsl --update --pre-release`, verify the installed version with `wsl --version`, and enable the Virtual Machine Platform optional component if required. The WSLC SDK DLL is a separate dependency and does not replace the WSL runtime package. |
| `WSLC image '<name>' not found locally` | Image was not pre-pulled, and no `imageTarPath` is set | Run `.\scripts\setup-wslc.ps1 -Image <name>` (or `wxc-exec.exe --setup-wslc --image <name>`); match the `-StoragePath` to your config's `experimental.wslc.storagePath` if set |
| `WSLC is an experimental feature` | Missing `--experimental` flag | Add `--experimental` to CLI or `{ experimental: true }` in SDK |
| `experimental mode` error in SDK | `SandboxSpawnOptions.experimental` not set | Pass `{ experimental: true }` to spawn functions |
Expand Down
4 changes: 2 additions & 2 deletions docs/wsl/wsl-container-support-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ script locates the DLL by architecture.
Implements `ScriptRunner` trait. Orchestrates the full lifecycle using WSLC SDK:

1. `initialize()`:
- Call `WslcGetMissingComponents()` β€” fail fast if WSLC runtime is not available
- Call `WslcGetMissingComponents()` β€” fail fast if the WSLC runtime is unavailable
- Call `WslcInitSessionSettings()` with storage path
- Configure session: CPU count, memory, timeout from `ContainerConfig`
- Call `WslcSessionCreate()` to start the WSL2 micro-VM
Expand Down Expand Up @@ -277,7 +277,7 @@ Implements `ScriptRunner` trait. Orchestrates the full lifecycle using WSLC SDK:
**Cleanup and error handling:**
- On normal exit: release process β†’ stop container β†’ delete container β†’ terminate session (reverse creation order)
- On crash/signal: register a `ctrlc` handler that runs the same cleanup sequence
- If WSLC runtime is not available: `WslcGetMissingComponents()` reports missing components β€” fail fast with a clear message listing what needs to be installed
- If the WSLC runtime is unavailable: `WslcGetMissingComponents()` reports missing components β€” fail fast with a clear message listing what needs to be installed
- If image is not found: fail fast with a clear error message listing the expected image name
- HRESULT error codes from WSLC SDK are translated to descriptive Rust errors

Expand Down
81 changes: 76 additions & 5 deletions src/backends/wslc/common/src/wsl_container_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,39 @@ fn sdk_error(context: &str, hr: HRESULT, sdk_msg: &str) -> ScriptResponse {
ScriptResponse::error(&msg)
}

/// Builds a user-facing prerequisite error for the components `WslcGetMissingComponents`
/// reports as missing. `missing` may combine multiple bits, and the guidance is branched
/// per-component so a user missing only `VirtualMachinePlatform` isn't told to update WSL
/// (which doesn't enable that Windows optional feature), and vice versa.
fn wslc_prerequisite_error(missing: WslcComponentFlags) -> String {
let needs_vmp =
missing.0 & WslcComponentFlags::WSLC_COMPONENT_FLAG_VIRTUAL_MACHINE_PLATFORM.0 != 0;
let needs_wsl_package = missing.0 & WslcComponentFlags::WSLC_COMPONENT_FLAG_WSL_PACKAGE.0 != 0;

let mut guidance = Vec::new();
if needs_vmp {
guidance.push(
"enable the \"Virtual Machine Platform\" Windows optional feature (Settings > \
Apps > Optional features > More Windows features, or run `dism.exe /online \
/enable-feature /featurename:VirtualMachinePlatform /all`) and restart"
.to_string(),
);
}
if needs_wsl_package {
guidance
.push("install WSL 2.9.3 or newer and run `wsl --update --pre-release`".to_string());
}
if guidance.is_empty() {
guidance.push("ensure WSL2 and the WSLC SDK are installed".to_string());
}

format!(
"WSLC runtime unavailable. Missing components: {}. Please {}.",
missing,
guidance.join("; "),
)
}

impl ScriptRunner for WSLContainerRunner {
fn execute(&mut self, request: &ExecutionRequest, logger: &mut Logger) -> ScriptResponse {
unsafe { self.run_internal(request, logger) }
Expand Down Expand Up @@ -355,11 +388,7 @@ impl WSLContainerRunner {
return Err(sdk_error("WslcGetMissingComponents failed", hr, ""));
}
if missing.any_missing() {
return Err(ScriptResponse::error(&format!(
"WSLC runtime not available. Missing components: {}. \
Ensure WSL2 and the WSLC SDK are installed.",
missing
)));
return Err(ScriptResponse::error(&wslc_prerequisite_error(missing)));
}
let _ = writeln!(logger, "[WSLC] Runtime check passed");

Expand Down Expand Up @@ -1496,4 +1525,46 @@ mod tests {
response.error_message
);
}

#[test]
fn prerequisite_error_for_wsl_package_missing() {
let message = wslc_prerequisite_error(WslcComponentFlags::WSLC_COMPONENT_FLAG_WSL_PACKAGE);

assert!(message.contains("WslPackage"));
assert!(message.contains("2.9.3"));
assert!(message.contains("wsl --update --pre-release"));
assert!(!message.contains("Virtual Machine Platform"));
}

#[test]
fn prerequisite_error_for_virtual_machine_platform_missing() {
let message = wslc_prerequisite_error(
WslcComponentFlags::WSLC_COMPONENT_FLAG_VIRTUAL_MACHINE_PLATFORM,
);

assert!(message.contains("VirtualMachinePlatform"));
assert!(message.contains("Virtual Machine Platform"));
assert!(!message.contains("wsl --update"));
}

#[test]
fn prerequisite_error_for_combined_missing_components() {
let combined = WslcComponentFlags::WSLC_COMPONENT_FLAG_VIRTUAL_MACHINE_PLATFORM
| WslcComponentFlags::WSLC_COMPONENT_FLAG_WSL_PACKAGE;
let message = wslc_prerequisite_error(combined);

assert!(message.contains("VirtualMachinePlatform"));
assert!(message.contains("WslPackage"));
assert!(message.contains("wsl --update"));
assert!(message.contains("Virtual Machine Platform"));
}

#[test]
fn prerequisite_error_for_sdk_needs_update() {
let message =
wslc_prerequisite_error(WslcComponentFlags::WSLC_COMPONENT_FLAG_SDK_NEEDS_UPDATE);

assert!(message.contains("SdkNeedsUpdate"));
assert!(message.contains("ensure WSL2 and the WSLC SDK are installed"));
}
}
Loading