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
};