From f40060b1b1ff4417d55ea5ea814104b7a6a15584 Mon Sep 17 00:00:00 2001 From: "Gordon Lam (SH)" Date: Mon, 16 Mar 2026 18:09:42 +0800 Subject: [PATCH] fix(service): improve error diagnostics for distribution start failures Adds more descriptive error messages and logging for CreateInstance/E_FAIL failures (error code 16, step 2). Users now get actionable guidance instead of opaque error codes. Fixes #14045 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- localization/strings/en-US/Resources.resw | 22 +++++++- src/windows/service/exe/WslCoreInstance.cpp | 57 ++++++++++++++++++++- src/windows/service/exe/WslCoreVm.cpp | 28 ++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) diff --git a/localization/strings/en-US/Resources.resw b/localization/strings/en-US/Resources.resw index 55a700b83..f1eef3d98 100644 --- a/localization/strings/en-US/Resources.resw +++ b/localization/strings/en-US/Resources.resw @@ -1036,9 +1036,29 @@ Falling back to NAT networking. {FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated - The distribution failed to start. Error code: {}, failure step: {} + The distribution failed to start. Failure step: {} ({}). Linux error code: {}. {FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated + + The distribution failed to start because WSL could not mount the distribution's virtual disk. Failure step: {} ({}). Linux error code: {}. +Check the distribution's disk and any disk-related settings in .wslconfig, such as 'swapFile', before trying again. + {FixedPlaceholder="{}"}{Locked=".wslconfig"}{Locked="swapFile"}Command line arguments, file names and string inserts should not be translated + + + format the distribution's virtual disk + + + mount the distribution's virtual disk + + + launch the distribution + + + complete distribution import + + + start the distribution + The distribution failed to start because its virtual disk is corrupted. diff --git a/src/windows/service/exe/WslCoreInstance.cpp b/src/windows/service/exe/WslCoreInstance.cpp index 74fe3168d..6bdce40a6 100644 --- a/src/windows/service/exe/WslCoreInstance.cpp +++ b/src/windows/service/exe/WslCoreInstance.cpp @@ -15,6 +15,29 @@ Module Name: #include "precomp.h" #include "WslCoreInstance.h" +namespace { +std::wstring CreateInstanceStepDescription(_In_ LX_MINI_CREATE_INSTANCE_STEP step) +{ + switch (step) + { + case LxInitCreateInstanceStepFormatDisk: + return wsl::shared::Localization::MessageCreateInstanceStepFormatDisk(); + + case LxInitCreateInstanceStepMountDisk: + return wsl::shared::Localization::MessageCreateInstanceStepMountDisk(); + + case LxInitCreateInstanceStepLaunchSystemDistro: + return wsl::shared::Localization::MessageCreateInstanceStepLaunchDistribution(); + + case LxInitCreateInstanceStepRunTar: + return wsl::shared::Localization::MessageCreateInstanceStepRunTar(); + + default: + return wsl::shared::Localization::MessageCreateInstanceStepUnknown(); + } +} +} // namespace + WslCoreInstance::WslCoreInstance( _In_ HANDLE UserToken, _In_ wil::unique_socket& InitSocket, @@ -57,17 +80,49 @@ WslCoreInstance::WslCoreInstance( } } + const auto stepDescription = CreateInstanceStepDescription(result.FailureStep); + WSL_LOG( + "CreateInstanceGuestResult", + TraceLoggingValue(m_configuration.Name.c_str(), "distroName"), + TraceLoggingValue(m_instanceId, "instanceId"), + TraceLoggingValue(m_runtimeId, "vmId"), + TraceLoggingValue(result.Result, "linuxError"), + TraceLoggingValue(static_cast(result.FailureStep), "failureStep"), + TraceLoggingValue(stepDescription.c_str(), "failureStepDescription"), + TraceLoggingValue(result.Pid, "pid"), + TraceLoggingValue(result.ConnectPort, "connectPort")); + if (result.Result != 0) { + WSL_LOG( + "CreateInstanceGuestFailure", + TraceLoggingLevel(WINEVENT_LEVEL_WARNING), + TraceLoggingValue(m_configuration.Name.c_str(), "distroName"), + TraceLoggingValue(m_instanceId, "instanceId"), + TraceLoggingValue(m_runtimeId, "vmId"), + TraceLoggingValue(result.Result, "linuxError"), + TraceLoggingValue(static_cast(result.FailureStep), "failureStep"), + TraceLoggingValue(stepDescription.c_str(), "failureStepDescription")); + // N.B. EUCLEAN (117) can be returned if the disk's journal is corrupted. if ((result.Result == EINVAL || result.Result == 117) && result.FailureStep == LxInitCreateInstanceStepMountDisk) { THROW_HR(WSL_E_DISK_CORRUPTED); } + else if (result.FailureStep == LxInitCreateInstanceStepMountDisk) + { + wsl::windows::common::ExecutionContext stepContext(wsl::windows::common::Context::MountDisk); + THROW_HR_WITH_USER_ERROR( + E_FAIL, + wsl::shared::Localization::MessageDistributionFailedToStartMountDisk( + static_cast(result.FailureStep), stepDescription, result.Result)); + } else { THROW_HR_WITH_USER_ERROR( - E_FAIL, wsl::shared::Localization::MessageDistributionFailedToStart(result.Result, static_cast(result.FailureStep))); + E_FAIL, + wsl::shared::Localization::MessageDistributionFailedToStart( + static_cast(result.FailureStep), stepDescription, result.Result)); } } diff --git a/src/windows/service/exe/WslCoreVm.cpp b/src/windows/service/exe/WslCoreVm.cpp index 952ff7f34..7f59e0ddf 100644 --- a/src/windows/service/exe/WslCoreVm.cpp +++ b/src/windows/service/exe/WslCoreVm.cpp @@ -1164,10 +1164,23 @@ std::shared_ptr WslCoreVm::CreateInstance( _In_ ULONG ExportFlags, _Out_opt_ ULONG* ConnectPort) { + WSL_LOG( + "CreateInstanceAttachDiskBegin", + TraceLoggingValue(Configuration.Name.c_str(), "distroName"), + TraceLoggingValue(InstanceId, "instanceId"), + TraceLoggingValue(m_runtimeId, "vmId")); + // Add the VHD to the machine. auto lock = m_lock.lock_exclusive(); const auto lun = AttachDiskLockHeld(Configuration.VhdFilePath.c_str(), DiskType::VHD, MountFlags::None, {}, false, m_userToken.get()); + WSL_LOG( + "CreateInstanceAttachDiskEnd", + TraceLoggingValue(Configuration.Name.c_str(), "distroName"), + TraceLoggingValue(InstanceId, "instanceId"), + TraceLoggingValue(m_runtimeId, "vmId"), + TraceLoggingValue(lun, "lun")); + // Launch the init daemon and create the instance. int flags = LxMiniInitMessageFlagNone; std::wstring sharedMemoryRoot{}; @@ -1208,6 +1221,21 @@ std::shared_ptr WslCoreVm::CreateInstance( message.WriteString(message->UserProfileOffset, userProfile); m_miniInitChannel.SendMessage(message.Span()); + WSL_LOG( + "CreateInstanceLaunchMessageSent", + TraceLoggingValue(Configuration.Name.c_str(), "distroName"), + TraceLoggingValue(InstanceId, "instanceId"), + TraceLoggingValue(m_runtimeId, "vmId"), + TraceLoggingValue(static_cast(MessageType), "messageType"), + TraceLoggingValue(flags, "flags"), + TraceLoggingValue(WI_IsFlagSet(flags, LxMiniInitMessageFlagLaunchSystemDistro), "launchSystemDistro")); + + WSL_LOG( + "CreateInstanceAwaitGuestResult", + TraceLoggingValue(Configuration.Name.c_str(), "distroName"), + TraceLoggingValue(InstanceId, "instanceId"), + TraceLoggingValue(m_runtimeId, "vmId")); + return CreateInstanceInternal( InstanceId, Configuration, ReceiveTimeout, DefaultUid, ClientLifetimeId, WI_IsFlagSet(flags, LxMiniInitMessageFlagLaunchSystemDistro), ConnectPort); }