Add a 'Error information from the engine:' prefix to error messages returned from docker when the current display language is not english (#41187)

* Add a 'Error information from the engine:' prefix to error messages returned from docker when the current display language is not english * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Fix broken copilot suggestion * Apply PR feedback --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Blue committed Jul 28, 2026 at 23:45 UTC 8d341e3513459f564df7a13da7311e02048fc12e
7 files changed +62 -17
localization/strings/en-US/Resources.resw
+3
@@ -2155,6 +2155,9 @@ Usage:
2155 <data name="MessageWslcNetworkNameRequired" xml:space="preserve">
2156 <value>Network name cannot be empty.</value>
2157 </data>
2158 + <data name="MessageWslcDockerEngineErrorPrefix" xml:space="preserve">
2159 + <value>Error information from the engine:</value>
2160 + </data>
2161 <data name="WSLCCLI_UnrecognizedCommandError" xml:space="preserve">
2162 <value>Unrecognized command: '{}'</value>
2163 <comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
src/windows/common/Localization.cpp
+18
@@ -100,3 +100,21 @@ LPCWSTR wsl::shared::Localization::LookupString(const std::vector<std::pair<std:
100 // Default to English is string is not found (English is always the first entry)
101 return strings[0].second;
102 }
103 +
104 +bool wsl::shared::Localization::IsCurrentLanguageEnglish(Options options)
105 +{
106 + try
107 + {
108 + const auto languages = GetUserLanguages(options != Options::DontImpersonate && g_runningInService);
109 + if (!languages.empty())
110 + {
111 + return languages[0] == L"en" || languages[0].starts_with(L"en-");
112 + }
113 + }
114 + catch (...)
115 + {
116 + LOG_CAUGHT_EXCEPTION();
117 + }
118 +
119 + return true;
120 +}
src/windows/wslcsession/DockerHTTPClient.cpp
+10
@@ -56,6 +56,16 @@ bool IsResponseChunked(const http::response_parser<http::buffer_body>::value_typ
56
57 } // namespace
58
59 +std::string wsl::windows::service::wslc::FormatDockerEngineError(const std::string& EngineMessage)
60 +{
61 + if (EngineMessage.empty() || wsl::shared::Localization::IsCurrentLanguageEnglish())
62 + {
63 + return EngineMessage;
64 + }
65 +
66 + return wsl::shared::string::WideToMultiByte(wsl::shared::Localization::MessageWslcDockerEngineErrorPrefix()) + " " + EngineMessage;
67 +}
68 +
69 DockerHTTPClient::URL::URL(std::string&& Path) : m_path(std::move(Path))
70 {
71 }
src/windows/wslcsession/DockerHTTPClient.h
+7 -1
@@ -26,7 +26,11 @@ Abstract:
26 if ((_Ex).HasErrorMessage()) \
27 { \
28 THROW_HR_WITH_USER_ERROR_MSG( \
29 - (_Ex).HResultFromStatusCode(), (_Ex).DockerMessage<wsl::windows::common::docker_schema::ErrorResponse>().message, _Msg, ##__VA_ARGS__); \
29 + (_Ex).HResultFromStatusCode(), \
30 + wsl::windows::service::wslc::FormatDockerEngineError( \
31 + (_Ex).DockerMessage<wsl::windows::common::docker_schema::ErrorResponse>().message), \
32 + _Msg, \
33 + ##__VA_ARGS__); \
34 } \
35 else \
36 { \
@@ -41,6 +45,8 @@ Abstract:
45
46 namespace wsl::windows::service::wslc {
47
48 +std::string FormatDockerEngineError(const std::string& EngineMessage);
49 +
50 class DockerHTTPException : public std::runtime_error
51 {
52 public:
src/windows/wslcsession/WSLCContainer.cpp
+9 -6
@@ -1192,9 +1192,10 @@ void WSLCContainerImpl::Export(WSLCHandle OutHandle) const
1192 {
1193 // Export failed, parse the error message.
1194 auto error = wsl::shared::FromJson<common::docker_schema::ErrorResponse>(errorJson.c_str());
1195 + const auto errorMessage = FormatDockerEngineError(error.message);
1196
1196 - THROW_HR_WITH_USER_ERROR_IF(WSLC_E_CONTAINER_NOT_FOUND, error.message, SocketCodePair.first == 404);
1197 - THROW_HR_WITH_USER_ERROR(E_FAIL, error.message);
1197 + THROW_HR_WITH_USER_ERROR_IF(WSLC_E_CONTAINER_NOT_FOUND, errorMessage, SocketCodePair.first == 404);
1198 + THROW_HR_WITH_USER_ERROR(E_FAIL, errorMessage);
1199 }
1200 }
1201
@@ -1253,9 +1254,10 @@ void WSLCContainerImpl::UploadArchive(WSLCHandle TarHandle, LPCSTR DestPath, ULO
1254 if (pendingErrorJson.has_value())
1255 {
1256 auto error = wsl::shared::FromJson<ErrorResponse>(pendingErrorJson->c_str());
1257 + const auto errorMessage = FormatDockerEngineError(error.message);
1258
1257 - THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), error.message, httpStatusCode == 404);
1258 - THROW_HR_WITH_USER_ERROR(E_FAIL, error.message);
1259 + THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), errorMessage, httpStatusCode == 404);
1260 + THROW_HR_WITH_USER_ERROR(E_FAIL, errorMessage);
1261 }
1262 }
1263
@@ -1300,9 +1302,10 @@ void WSLCContainerImpl::DownloadArchive(LPCSTR SrcPath, WSLCHandle OutHandle) co
1302 if (statusCode != 200)
1303 {
1304 auto error = wsl::shared::FromJson<ErrorResponse>(errorJson.c_str());
1305 + const auto errorMessage = FormatDockerEngineError(error.message);
1306
1304 - THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), error.message, statusCode == 404);
1305 - THROW_HR_WITH_USER_ERROR(E_FAIL, error.message);
1307 + THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), errorMessage, statusCode == 404);
1308 + THROW_HR_WITH_USER_ERROR(E_FAIL, errorMessage);
1309 }
1310 }
1311
src/windows/wslcsession/WSLCSession.cpp
+11 -10
@@ -769,7 +769,7 @@ void WSLCSession::StreamImageOperation(DockerHTTPClient::HTTPRequestContext& req
769 EMIT_USER_WARNING(wsl::shared::string::MultiByteToWide(*reportedError));
770 }
771
772 - reportedError = parsed.errorDetail->message;
772 + reportedError = FormatDockerEngineError(parsed.errorDetail->message);
773 return;
774 }
775
@@ -792,7 +792,7 @@ void WSLCSession::StreamImageOperation(DockerHTTPClient::HTTPRequestContext& req
792 if (httpResponse->isJson)
793 {
794 // operation failed, parse the error message.
795 - errorMessage = wsl::shared::FromJson<docker_schema::ErrorResponse>(errorJson.c_str()).message;
795 + errorMessage = FormatDockerEngineError(wsl::shared::FromJson<docker_schema::ErrorResponse>(errorJson.c_str()).message);
796 }
797 else
798 {
@@ -1347,7 +1347,7 @@ std::optional<std::string> WSLCSession::ImportImageImpl(DockerHTTPClient::HTTPRe
1347 EMIT_USER_WARNING(wsl::shared::string::MultiByteToWide(*errorMessage));
1348 }
1349
1350 - errorMessage = std::move(parsed.errorDetail->message);
1350 + errorMessage = FormatDockerEngineError(parsed.errorDetail->message);
1351 }
1352 else if (parsed.stream.has_value())
1353 {
@@ -1420,7 +1420,7 @@ std::optional<std::string> WSLCSession::ImportImageImpl(DockerHTTPClient::HTTPRe
1420 {
1421 auto error = wsl::shared::FromJson<docker_schema::ErrorResponse>(pendingErrorJson->c_str());
1422
1423 - THROW_HR_WITH_USER_ERROR(E_FAIL, error.message);
1423 + THROW_HR_WITH_USER_ERROR(E_FAIL, FormatDockerEngineError(error.message));
1424 }
1425
1426 // Otherwise look for an error message returned via the progress stream (HTTP 200 followed by a stream error).
@@ -1512,8 +1512,9 @@ void WSLCSession::SaveImageImpl(std::pair<uint32_t, wil::unique_socket>& SocketC
1512 {
1513 // Save failed, parse the error message.
1514 auto error = wsl::shared::FromJson<docker_schema::ErrorResponse>(errorJson.c_str());
1515 - THROW_HR_WITH_USER_ERROR_IF(WSLC_E_IMAGE_NOT_FOUND, error.message, SocketCodePair.first == 404);
1516 - THROW_HR_WITH_USER_ERROR(E_FAIL, error.message.c_str());
1515 + const auto errorMessage = FormatDockerEngineError(error.message);
1516 + THROW_HR_WITH_USER_ERROR_IF(WSLC_E_IMAGE_NOT_FOUND, errorMessage, SocketCodePair.first == 404);
1517 + THROW_HR_WITH_USER_ERROR(E_FAIL, errorMessage);
1518 }
1519 }
1520
@@ -1670,7 +1671,7 @@ try
1671 std::string errorMessage;
1672 if ((e.StatusCode() >= 400 && e.StatusCode() < 500))
1673 {
1673 - errorMessage = e.DockerMessage<docker_schema::ErrorResponse>().message;
1674 + errorMessage = FormatDockerEngineError(e.DockerMessage<docker_schema::ErrorResponse>().message);
1675 }
1676
1677 THROW_HR_WITH_USER_ERROR_IF(WSLC_E_IMAGE_NOT_FOUND, errorMessage, e.StatusCode() == 404);
@@ -1742,7 +1743,7 @@ try
1743 std::string errorMessage;
1744 if ((e.StatusCode() >= 400 && e.StatusCode() < 500))
1745 {
1745 - errorMessage = e.DockerMessage<docker_schema::ErrorResponse>().message;
1746 + errorMessage = FormatDockerEngineError(e.DockerMessage<docker_schema::ErrorResponse>().message);
1747 }
1748
1749 THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_BAD_ARGUMENTS), errorMessage, e.StatusCode() == 400);
@@ -1810,7 +1811,7 @@ std::string WSLCSession::InspectImageLockHeld(const std::string& NameOrId)
1811 std::string errorMessage = "Failed to inspect image";
1812 if (e.HasErrorMessage())
1813 {
1813 - errorMessage = e.DockerMessage<docker_schema::ErrorResponse>().message;
1814 + errorMessage = FormatDockerEngineError(e.DockerMessage<docker_schema::ErrorResponse>().message);
1815 }
1816
1817 THROW_HR_WITH_USER_ERROR_IF(WSLC_E_IMAGE_NOT_FOUND, errorMessage, e.StatusCode() == 404);
@@ -2021,7 +2022,7 @@ void WSLCSession::CreateContainerImpl(const WSLCContainerOptions* containerOptio
2022 std::string errorMessage;
2023 if ((e.StatusCode() >= 400 && e.StatusCode() < 500))
2024 {
2024 - errorMessage = e.DockerMessage<docker_schema::ErrorResponse>().message;
2025 + errorMessage = FormatDockerEngineError(e.DockerMessage<docker_schema::ErrorResponse>().message);
2026 }
2027
2028 THROW_HR_WITH_USER_ERROR_IF(WSLC_E_IMAGE_NOT_FOUND, errorMessage, e.StatusCode() == 404);
tools/generateLocalizationHeader.ps1
+4
@@ -166,6 +166,10 @@ foreach($entry in $allStrings[$defaultLanguage].Keys)
166 }
167
168 $content += @"
169 +public:
170 +#ifdef WIN32
171 + static bool IsCurrentLanguageEnglish(Options options = Options::Default);
172 +#endif
173 private:
174 static const TChar* LookupString(const std::vector<std::pair<TString, const TChar*>>& strings, Options options);
175 };