diff --git a/a2a-t-core/src/main/java/net/openan/a2at/sdk/core/exception/ErrorCatalog.java b/a2a-t-core/src/main/java/net/openan/a2at/sdk/core/exception/ErrorCatalog.java index f890661a..ae918c36 100644 --- a/a2a-t-core/src/main/java/net/openan/a2at/sdk/core/exception/ErrorCatalog.java +++ b/a2a-t-core/src/main/java/net/openan/a2at/sdk/core/exception/ErrorCatalog.java @@ -13,9 +13,10 @@ * Closed catalog of the machine-readable error codes exposed by the A2A-T SDK. * *
Each constant carries the layered {@code domain.semantic} code string (for example {@code content.param_missing}), - * the {@link Category} that decides which exception family carries it, and the names of the fact parameters the message - * template for the code renders. Message templates live in {@code prompt_resources/errors/{language}/errors.json}; use - * {@link ErrorMessages} to render them. + * the {@link Category} that decides which exception family carries it, and the names of the fact parameters the code + * declares. A message template may render a subset of the declared facts: {@code template.not_found} keeps + * {@code language} in its facts for programmatic diagnosis while its message only reports the missing template. Message + * templates live in {@code prompt_resources/errors/{language}/errors.json}; use {@link ErrorMessages} to render them. * *
The catalog is closed: codes returned by an LLM step that are not in this catalog are mapped to the per-domain
* {@code *.rule_violation} fallback constants by the callers, never surfaced raw.
@@ -26,7 +27,7 @@ public enum ErrorCatalog {
// domain: template (template resources)
- /** The referenced template does not exist for the configured language. */
+ /** The referenced template is missing for the configured language; the message names the template URI. */
TEMPLATE_NOT_FOUND("template.not_found", Category.BUSINESS, "template_uri", "language"),
/** Rendering a template with its slot values failed. */
@@ -222,7 +223,10 @@ public static Optional A message template may render a subset of these facts; the remaining ones stay available for programmatic
+ * diagnosis.
*
* @return fact parameter names, possibly empty, never null
*/
diff --git a/a2a-t-resources/src/main/resources/prompt_resources/errors/en-US/errors.json b/a2a-t-resources/src/main/resources/prompt_resources/errors/en-US/errors.json
index b90a18d2..17ee93a8 100644
--- a/a2a-t-resources/src/main/resources/prompt_resources/errors/en-US/errors.json
+++ b/a2a-t-resources/src/main/resources/prompt_resources/errors/en-US/errors.json
@@ -1,5 +1,5 @@
{
- "template.not_found": "Template '{template_uri}' does not support language '{language}'; check the template URI and language setting",
+ "template.not_found": "Template '{template_uri}' does not exist",
"template.render_failed": "Failed to render template '{template_uri}': {reason}",
"template.load_failed": "Failed to read template resource '{resource_path}'",
"slot.schema_not_found": "Template '{template_uri}' is missing its slot schema (language '{language}')",
diff --git a/a2a-t-resources/src/main/resources/prompt_resources/errors/zh-CN/errors.json b/a2a-t-resources/src/main/resources/prompt_resources/errors/zh-CN/errors.json
index a42f8c7d..90cce849 100644
--- a/a2a-t-resources/src/main/resources/prompt_resources/errors/zh-CN/errors.json
+++ b/a2a-t-resources/src/main/resources/prompt_resources/errors/zh-CN/errors.json
@@ -1,5 +1,5 @@
{
- "template.not_found": "模板「{template_uri}」不支持语言「{language}」,请检查模板标识与语言配置",
+ "template.not_found": "模板「{template_uri}」不存在",
"template.render_failed": "模板「{template_uri}」渲染失败:{reason}",
"template.load_failed": "模板资源「{resource_path}」读取失败",
"slot.schema_not_found": "模板「{template_uri}」缺少参数定义文件(语言「{language}」)",
diff --git a/a2a-t-resources/src/test/java/net/openan/a2at/sdk/resources/ErrorMessagesResourceTest.java b/a2a-t-resources/src/test/java/net/openan/a2at/sdk/resources/ErrorMessagesResourceTest.java
new file mode 100644
index 00000000..e5359b50
--- /dev/null
+++ b/a2a-t-resources/src/test/java/net/openan/a2at/sdk/resources/ErrorMessagesResourceTest.java
@@ -0,0 +1,58 @@
+package net.openan.a2at.sdk.resources;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.util.Map;
+import net.openan.a2at.sdk.core.exception.ErrorCatalog;
+import net.openan.a2at.sdk.core.exception.ErrorMessages;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Integration tests for the bundled {@code prompt_resources/errors/{language}/errors.json} resources rendered through
+ * {@link ErrorMessages}.
+ *
+ * Tests cover the following scenarios:
+ *
+ * Scenario: Render the catalog entry with a template URI and an unsupported language. Expected result: the
+ * message states the template does not exist and omits the language.
+ */
+ @Test
+ void should_reportMissingTemplate_When_renderedInChinese() {
+ String message = ErrorMessages.render(ErrorCatalog.TEMPLATE_NOT_FOUND, "zh-CN", FACTS);
+
+ assertEquals("模板「" + UNKNOWN_URI + "」不存在", message);
+ assertFalse(message.contains("fr-FR"), message);
+ }
+
+ /**
+ * Verifies the bundled English {@code template.not_found} message reports the missing template and does not echo
+ * the configured language.
+ *
+ * Scenario: Render the catalog entry with a template URI and an unsupported language. Expected result: the
+ * message states the template does not exist and omits the language.
+ */
+ @Test
+ void should_reportMissingTemplate_When_renderedInEnglish() {
+ String message = ErrorMessages.render(ErrorCatalog.TEMPLATE_NOT_FOUND, "en-US", FACTS);
+
+ assertEquals("Template '" + UNKNOWN_URI + "' does not exist", message);
+ assertFalse(message.contains("fr-FR"), message);
+ }
+}
diff --git a/a2a-t-server/src/test/java/net/openan/a2at/sdk/server/metadata/LlmBackedPromptMetadataExtractorTest.java b/a2a-t-server/src/test/java/net/openan/a2at/sdk/server/metadata/LlmBackedPromptMetadataExtractorTest.java
index 3e1b8123..de63be6c 100644
--- a/a2a-t-server/src/test/java/net/openan/a2at/sdk/server/metadata/LlmBackedPromptMetadataExtractorTest.java
+++ b/a2a-t-server/src/test/java/net/openan/a2at/sdk/server/metadata/LlmBackedPromptMetadataExtractorTest.java
@@ -1,6 +1,7 @@
package net.openan.a2at.sdk.server.metadata;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -235,7 +236,11 @@ void extractPropagatesTemplateLoadErrorsAsGenerationFailures() {
assertEquals("template.not_found", error.getCode());
assertEquals("generation", error.getStage());
assertTrue(error.getMessage().contains("subscribe-incident"), "message must render the template URI");
- assertTrue(error.getMessage().contains("zh-CN"), "message must render the language");
+ assertFalse(error.getMessage().contains("zh-CN"), "message must not echo the configured language");
+ assertEquals(
+ Map.of("template_uri", "subscribe-incident", "language", "zh-CN"),
+ error.getFacts(),
+ "facts must keep the language for programmatic diagnosis");
}
@Test
diff --git a/docs/en/API_Reference.md b/docs/en/API_Reference.md
index ac7c57b1..2390fe57 100644
--- a/docs/en/API_Reference.md
+++ b/docs/en/API_Reference.md
@@ -1639,7 +1639,7 @@ result.failure() =
| Code | Category | Message (en-US) | Message (zh-CN) |
| ---- | -------- | ---------------- | --------------- |
-| `template.not_found` | BUSINESS | Template '{template_uri}' does not support language '{language}'; check the template URI and language setting | 模板「{template_uri}」不支持语言「{language}」,请检查模板标识与语言配置 |
+| `template.not_found` | BUSINESS | Template '{template_uri}' does not exist | 模板「{template_uri}」不存在 |
| `template.render_failed` | BUSINESS | Failed to render template '{template_uri}': {reason} | 模板「{template_uri}」渲染失败:{reason} |
| `template.load_failed` | INFRA | Failed to read template resource '{resource_path}' | 模板资源「{resource_path}」读取失败 |
| `slot.schema_not_found` | BUSINESS | Template '{template_uri}' is missing its slot schema (language '{language}') | 模板「{template_uri}」缺少参数定义文件(语言「{language}」) |
diff --git "a/docs/zh/API\345\217\202\350\200\203.md" "b/docs/zh/API\345\217\202\350\200\203.md"
index 6712a7bd..0f298f22 100644
--- "a/docs/zh/API\345\217\202\350\200\203.md"
+++ "b/docs/zh/API\345\217\202\350\200\203.md"
@@ -1630,7 +1630,7 @@ result.failure() =
| 错误码 | 类别 | 消息(zh-CN) | 消息(en-US) |
| ----------------------------------------- | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
-| `template.not_found` | BUSINESS | 模板「{template_uri}」不支持语言「{language}」,请检查模板标识与语言配置 | Template '{template_uri}' does not support language '{language}'; check the template URI and language setting |
+| `template.not_found` | BUSINESS | 模板「{template_uri}」不存在 | Template '{template_uri}' does not exist |
| `template.render_failed` | BUSINESS | 模板「{template_uri}」渲染失败:{reason} | Failed to render template '{template_uri}': {reason} |
| `template.load_failed` | INFRA | 模板资源「{resource_path}」读取失败 | Failed to read template resource '{resource_path}' |
| `slot.schema_not_found` | BUSINESS | 模板「{template_uri}」缺少参数定义文件(语言「{language}」) | Template '{template_uri}' is missing its slot schema (language '{language}') |
+ *
+ *
+ * @since 2026-09
+ */
+class ErrorMessagesResourceTest {
+
+ private static final String UNKNOWN_URI = "Task-T/network-layer/does-not-exist/v1";
+
+ private static final Map