This is an automated email from the ASF dual-hosted git repository.

luigidemasi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 410257124006812d831c839f38e818416e9d6215
Author: Luigi De Masi <[email protected]>
AuthorDate: Sat Oct 10 14:37:03 2026 +0200

    CAMEL-25499: Classify semantic default-selection errors
    
    Classify missing or ambiguous automatic selection through a typed internal
    exception and expose a stable defaultErrorCode from semantic metadata.
    Let the CLI use the code with a compatibility fallback for older runtimes,
    while preserving real errors and the existing response constructor.
    
    Document the intentionally shared live/persisted audit-record validation
    and bounded defensive input copy. Add producer and CLI regressions and
    regenerate console metadata and catalog documentation.
    
    Co-authored-by: OpenAI Codex <[email protected]>
---
 .../apache/camel/catalog/dev-consoles-openapi.json |  4 ++
 .../catalog/dev-consoles/semantic-metadata.json    |  4 ++
 .../camel/catalog/docs/semantic-language.adoc      |  5 ++
 .../camel/dev-console/semantic-metadata.json       |  4 ++
 .../src/main/docs/semantic-language.adoc           |  5 ++
 .../camel/language/semantic/SemanticLanguage.java  |  5 +-
 .../apache/camel/semantic/SemanticAuditRecord.java |  2 +-
 .../camel/semantic/SemanticMetadataConsole.java    | 13 ++++-
 .../internal/NoUniqueSemanticExpertException.java  | 29 +++++++++++
 .../semantic/internal/SemanticAuditService.java    |  1 +
 .../semantic/SemanticMetadataConsoleTest.java      | 56 ++++++++++++++++++++++
 .../modules/ROOT/pages/camel-jbang-managing.adoc   |  4 +-
 .../jbang/core/commands/action/CamelSemantic.java  |  7 ++-
 .../core/commands/action/SemanticCommandTest.java  | 22 +++++++++
 14 files changed, 153 insertions(+), 8 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles-openapi.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles-openapi.json
index 1bfbf908ff0c..66dfb8d9507b 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles-openapi.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles-openapi.json
@@ -7435,6 +7435,10 @@
                                                                                
"defaultError": {
                                                                                
        "type": "string",
                                                                                
        "description": "Default selection error, if any"
+                                                                               
},
+                                                                               
"defaultErrorCode": {
+                                                                               
        "type": "string",
+                                                                               
        "description": "Default selection error code: no_unique_expert or 
default_expert_error"
                                                                                
}
                                                                        }
                                                                }
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/semantic-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/semantic-metadata.json
index 9f01551d9f8f..7ea4452ed6a2 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/semantic-metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/semantic-metadata.json
@@ -176,6 +176,10 @@
       "defaultError": {
         "type": "string",
         "description": "Default selection error, if any"
+      },
+      "defaultErrorCode": {
+        "type": "string",
+        "description": "Default selection error code: no_unique_expert or 
default_expert_error"
       }
     }
   }
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/semantic-language.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/semantic-language.adoc
index d2a930bf897f..e82cea82d6b7 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/semantic-language.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/semantic-language.adoc
@@ -914,6 +914,11 @@ Use `camel semantic` to inspect definitions and `camel 
semantic eval` to evaluat
 
xref:manual::camel-jbang-managing.adoc#_semantic_definitions_and_evaluation[Camel
 CLI].
 
 `semantic-metadata` exposes definitions and expert contracts without 
performing inference.
+With `overview=true`, a failed default selection includes `defaultError` and a 
stable
+`defaultErrorCode`: `no_unique_expert` means automatic discovery found zero or 
multiple
+eligible experts; `default_expert_error` identifies a configuration, contract 
or descriptor
+failure. Consumers can distinguish these cases without parsing the diagnostic 
message.
+
 `semantic-evaluate` evaluates a named definition against a sample exchange or 
calls an expert
 operation directly. It uses the configured provider and its normal validation, 
without sending
 the sample through an application route.
diff --git 
a/components/camel-ai/camel-semantic/src/generated/resources/META-INF/org/apache/camel/dev-console/semantic-metadata.json
 
b/components/camel-ai/camel-semantic/src/generated/resources/META-INF/org/apache/camel/dev-console/semantic-metadata.json
index 9f01551d9f8f..7ea4452ed6a2 100644
--- 
a/components/camel-ai/camel-semantic/src/generated/resources/META-INF/org/apache/camel/dev-console/semantic-metadata.json
+++ 
b/components/camel-ai/camel-semantic/src/generated/resources/META-INF/org/apache/camel/dev-console/semantic-metadata.json
@@ -176,6 +176,10 @@
       "defaultError": {
         "type": "string",
         "description": "Default selection error, if any"
+      },
+      "defaultErrorCode": {
+        "type": "string",
+        "description": "Default selection error code: no_unique_expert or 
default_expert_error"
       }
     }
   }
diff --git 
a/components/camel-ai/camel-semantic/src/main/docs/semantic-language.adoc 
b/components/camel-ai/camel-semantic/src/main/docs/semantic-language.adoc
index d2a930bf897f..e82cea82d6b7 100644
--- a/components/camel-ai/camel-semantic/src/main/docs/semantic-language.adoc
+++ b/components/camel-ai/camel-semantic/src/main/docs/semantic-language.adoc
@@ -914,6 +914,11 @@ Use `camel semantic` to inspect definitions and `camel 
semantic eval` to evaluat
 
xref:manual::camel-jbang-managing.adoc#_semantic_definitions_and_evaluation[Camel
 CLI].
 
 `semantic-metadata` exposes definitions and expert contracts without 
performing inference.
+With `overview=true`, a failed default selection includes `defaultError` and a 
stable
+`defaultErrorCode`: `no_unique_expert` means automatic discovery found zero or 
multiple
+eligible experts; `default_expert_error` identifies a configuration, contract 
or descriptor
+failure. Consumers can distinguish these cases without parsing the diagnostic 
message.
+
 `semantic-evaluate` evaluates a named definition against a sample exchange or 
calls an expert
 operation directly. It uses the configured provider and its normal validation, 
without sending
 the sample through an application route.
diff --git 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/language/semantic/SemanticLanguage.java
 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/language/semantic/SemanticLanguage.java
index ea64debe3cf4..ac7bbf6599f6 100644
--- 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/language/semantic/SemanticLanguage.java
+++ 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/language/semantic/SemanticLanguage.java
@@ -48,6 +48,7 @@ import org.apache.camel.semantic.SemanticEvaluation;
 import org.apache.camel.semantic.SemanticEvaluations;
 import org.apache.camel.semantic.SemanticExpert.ResultType;
 import org.apache.camel.semantic.SemanticResult;
+import org.apache.camel.semantic.internal.NoUniqueSemanticExpertException;
 import org.apache.camel.semantic.internal.SemanticAuditService;
 import org.apache.camel.spi.FactoryFinder;
 import org.apache.camel.spi.Metadata;
@@ -374,9 +375,7 @@ public class SemanticLanguage extends LanguageSupport {
         if (candidates.size() + instances.size() != 1) {
             Set<String> names = new TreeSet<>(registered.keySet());
             names.addAll(candidates);
-            throw new IllegalArgumentException(
-                    "Semantic language requires exactly one eligible expert; 
available experts: " + names
-                                               + ". Specify expert or 
configure camel.language.semantic.default-expert explicitly");
+            throw new NoUniqueSemanticExpertException(names);
         }
         if (instances.size() == 1) {
             SemanticAdapter instance = instances.iterator().next();
diff --git 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticAuditRecord.java
 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticAuditRecord.java
index cd996b2beaa5..13dfd58aab45 100644
--- 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticAuditRecord.java
+++ 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticAuditRecord.java
@@ -38,7 +38,7 @@ public final class SemanticAuditRecord {
         this.timestamp = Instant.parse((String) fields.get("timestamp"));
     }
 
-    /** Reconstruct a persisted version-1 record; rejects unknown fields and 
bounds nested data. */
+    /** Create or restore a version-1 record; rejects unknown fields and 
defensively copies bounded nested data. */
     public static SemanticAuditRecord fromMap(Map<String, ?> data) {
         Set<String> keys = Set.of("schemaVersion", "eventId", "invocationId", 
"timestamp", "category", "origin", "requestId",
                 "batchId", "definition", "target", "expert", "operation", 
"contextId", "exchangeId", "routeId", "semantics",
diff --git 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticMetadataConsole.java
 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticMetadataConsole.java
index 255c279fd30c..19776950316a 100644
--- 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticMetadataConsole.java
+++ 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/SemanticMetadataConsole.java
@@ -25,6 +25,7 @@ import java.util.Map;
 import java.util.TreeMap;
 
 import org.apache.camel.language.semantic.SemanticLanguage;
+import org.apache.camel.semantic.internal.NoUniqueSemanticExpertException;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.annotations.DevConsole;
 import org.apache.camel.support.console.AbstractDevConsole;
@@ -73,7 +74,13 @@ public class SemanticMetadataConsole extends 
AbstractDevConsole {
             @Metadata(description = "Known experts, when overview is 
requested") List<Expert> experts,
             @Metadata(description = "Published definitions, when overview is 
requested") List<Definition> evaluations,
             @Metadata(description = "Resolved default expert") String 
defaultExpert,
-            @Metadata(description = "Default selection error, if any") String 
defaultError) {
+            @Metadata(description = "Default selection error, if any") String 
defaultError,
+            @Metadata(description = "Default selection error code: 
no_unique_expert or default_expert_error") String defaultErrorCode) {
+
+        public Response(List<Operation> operations, List<Expert> experts, 
List<Definition> evaluations,
+                        String defaultExpert, String defaultError) {
+            this(operations, experts, evaluations, defaultExpert, 
defaultError, null);
+        }
     }
 
     public SemanticMetadataConsole() {
@@ -112,10 +119,12 @@ public class SemanticMetadataConsole extends 
AbstractDevConsole {
                 });
         String defaultExpert = null;
         String defaultError = null;
+        String defaultErrorCode = null;
         try {
             defaultExpert = addExpert(experts, language.describeExpert(null));
         } catch (IllegalArgumentException | IOException e) {
             defaultError = e.getMessage();
+            defaultErrorCode = e instanceof NoUniqueSemanticExpertException ? 
"no_unique_expert" : "default_expert_error";
         }
         List<Definition> definitions = new ArrayList<>();
         SemanticEvaluations registry = 
getCamelContext().getCamelContextExtension().getContextPlugin(SemanticEvaluations.class);
@@ -138,7 +147,7 @@ public class SemanticMetadataConsole extends 
AbstractDevConsole {
                         evaluation.getParameters(), resultType, error));
             });
         }
-        return new Response(null, List.copyOf(experts.values()), definitions, 
defaultExpert, defaultError);
+        return new Response(null, List.copyOf(experts.values()), definitions, 
defaultExpert, defaultError, defaultErrorCode);
     }
 
     private static String addExpert(Map<String, Expert> experts, 
SemanticLanguage.ExpertMetadata metadata) {
diff --git 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/NoUniqueSemanticExpertException.java
 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/NoUniqueSemanticExpertException.java
new file mode 100644
index 000000000000..ace6686d7a4c
--- /dev/null
+++ 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/NoUniqueSemanticExpertException.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.semantic.internal;
+
+import java.util.Set;
+
+/** Automatic discovery found zero or multiple eligible experts. */
+public final class NoUniqueSemanticExpertException extends 
IllegalArgumentException {
+    private static final long serialVersionUID = 1L;
+
+    public NoUniqueSemanticExpertException(Set<String> experts) {
+        super("Semantic language requires exactly one eligible expert; 
available experts: " + experts
+              + ". Specify expert or configure 
camel.language.semantic.default-expert explicitly");
+    }
+}
diff --git 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/SemanticAuditService.java
 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/SemanticAuditService.java
index bd8c000b4001..de2a56b1f102 100644
--- 
a/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/SemanticAuditService.java
+++ 
b/components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/SemanticAuditService.java
@@ -472,6 +472,7 @@ public final class SemanticAuditService extends 
ServiceSupport {
             }
             if (enabled) {
                 fields.putAll(inputFields);
+                // Keep live and restored records on the same validation path, 
including the bounded defensive input copy.
                 publish(inputFields.isEmpty() ? record : 
SemanticAuditRecord.fromMap(fields));
             }
         }
diff --git 
a/components/camel-ai/camel-semantic/src/test/java/org/apache/camel/semantic/SemanticMetadataConsoleTest.java
 
b/components/camel-ai/camel-semantic/src/test/java/org/apache/camel/semantic/SemanticMetadataConsoleTest.java
index 24119edc841c..93079a7aceeb 100644
--- 
a/components/camel-ai/camel-semantic/src/test/java/org/apache/camel/semantic/SemanticMetadataConsoleTest.java
+++ 
b/components/camel-ai/camel-semantic/src/test/java/org/apache/camel/semantic/SemanticMetadataConsoleTest.java
@@ -28,11 +28,62 @@ import org.apache.camel.semantic.SemanticExpert.ResultType;
 import org.apache.camel.support.PluginHelper;
 import org.apache.camel.util.json.JsonObject;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 class SemanticMetadataConsoleTest {
+    @ParameterizedTest
+    @ValueSource(ints = { 0, 2 })
+    void overviewClassifiesNonUniqueAutomaticSelection(int expertCount) throws 
Exception {
+        try (var context = new DefaultCamelContext()) {
+            for (int i = 0; i < expertCount; i++) {
+                context.getRegistry().bind("security" + i, new Detector());
+            }
+            context.start();
+            DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("semantic-metadata");
+            JsonObject response = (JsonObject) 
console.call(DevConsole.MediaType.JSON, Map.of("overview", true));
+            assertThat(response).containsEntry("defaultErrorCode", 
"no_unique_expert");
+            assertThat(response.getString("defaultError")).contains("requires 
exactly one eligible expert");
+            assertThat(response.get("defaultExpert")).isNull();
+            List<JsonObject> experts = response.getCollection("experts");
+            assertThat(experts).hasSize(expertCount);
+        }
+    }
+
+    @Test
+    void overviewResolvesTheOnlyExpertWithoutAnErrorCode() throws Exception {
+        try (var context = new DefaultCamelContext()) {
+            context.getRegistry().bind("security", new Detector());
+            context.start();
+            DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("semantic-metadata");
+            JsonObject response = (JsonObject) 
console.call(DevConsole.MediaType.JSON, Map.of("overview", true));
+            assertThat(response).containsEntry("defaultExpert", "security");
+            assertThat(response.get("defaultError")).isNull();
+            assertThat(response.get("defaultErrorCode")).isNull();
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "missing", "wrong-type", "invalid-contract" })
+    void overviewDistinguishesBrokenDefaultsFromAutomaticSelection(String 
expert) throws Exception {
+        try (var context = new DefaultCamelContext()) {
+            context.getRegistry().bind("security", new Detector());
+            context.getRegistry().bind("wrong-type", new Object());
+            context.getRegistry().bind("invalid-contract", new 
InvalidDetector());
+            var language = (SemanticLanguage) 
context.resolveLanguage("semantic");
+            language.setDefaultExpert(expert);
+            context.start();
+            DevConsole console = 
PluginHelper.getDevConsoleResolver(context).resolveDevConsole("semantic-metadata");
+            JsonObject response = (JsonObject) 
console.call(DevConsole.MediaType.JSON, Map.of("overview", true));
+            assertThat(response).containsEntry("defaultErrorCode", 
"default_expert_error");
+            assertThat(response.getString("defaultError")).isNotBlank();
+            assertThat(response.get("defaultExpert")).isNull();
+        }
+    }
+
     @Test
     void inspectionDoesNotSelectAnAdapterAndErrorsUseTheResolvedName() throws 
Exception {
         try (var context = new DefaultCamelContext()) {
@@ -133,4 +184,9 @@ class SemanticMetadataConsoleTest {
             throw new AssertionError("Metadata must not construct a 
class-discovered expert");
         }
     }
+
+    @SemanticExpert(name = "invalid", description = "Invalid contract", 
provider = "test", artifactId = "test",
+                    operations = {})
+    public static class InvalidDetector extends Detector {
+    }
 }
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
index 3d43c9edada4..7be473ac9496 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
@@ -301,7 +301,9 @@ definition names, experts, operations, state selectors, 
result types and resolut
 errors, followed by the known experts and default expert. Listing does not 
require a
 default expert: the text output shows `Default expert: none` when automatic 
selection has
 no eligible expert or is ambiguous. Configuration and contract-resolution 
errors still appear
-as `Default expert error`. `--json` retains all default-selection diagnostics. 
`--expert`
+as `Default expert error`. `--json` retains all default-selection diagnostics, 
including
+`defaultErrorCode` when provided by the runtime. The CLI uses that code to 
identify an
+absent or ambiguous automatic default and supports older runtimes that return 
only a message. `--expert`
 shows one expert's operations, input and result semantics, and parameter 
contract.
 Inspection does not perform inference. Use `--json` for machine-readable 
output.
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSemantic.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSemantic.java
index b29b478d8973..9f18a04f5788 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSemantic.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSemantic.java
@@ -98,7 +98,12 @@ public class CamelSemantic extends SemanticActionCommand {
         String defaultExpert = text(response, "defaultExpert");
         printer().println("Default expert: " + (defaultExpert.isEmpty() ? 
"none" : defaultExpert));
         String defaultError = text(response, "defaultError");
-        if (!defaultError.isEmpty() && !defaultError.startsWith("Semantic 
language requires exactly one eligible expert")) {
+        String defaultErrorCode = text(response, "defaultErrorCode");
+        // Older runtimes expose only the message; structured codes take 
precedence when available.
+        boolean noUniqueExpert = defaultErrorCode.isEmpty()
+                ? defaultError.startsWith("Semantic language requires exactly 
one eligible expert")
+                : "no_unique_expert".equals(defaultErrorCode);
+        if (!defaultError.isEmpty() && !noUniqueExpert) {
             printer().println("Default expert error: " + defaultError);
         }
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
index ed42f0128194..0945e52f599c 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
@@ -113,6 +113,27 @@ class SemanticCommandTest {
         assertEquals("", errors.toString());
     }
 
+    @Test
+    void listsExpertsUsingTheStructuredDefaultSelectionCode() throws Exception 
{
+        JsonObject response = json("{\"evaluations\":[],\"experts\":[]}");
+        response.put("defaultErrorCode", "no_unique_expert");
+        response.put("defaultError", "Automatic expert selection is 
unavailable");
+        assertEquals(0, respond(new CamelSemantic(main()), r -> response));
+        assertTrue(printer.getOutput().contains("Default expert: none"));
+        assertFalse(printer.getOutput().contains("Default expert error:"), 
printer.getOutput());
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "default_expert_error", "future_error_code" })
+    void structuredDefaultErrorsTakePrecedenceOverLegacyMessageMatching(String 
code) throws Exception {
+        JsonObject response = json("{\"evaluations\":[],\"experts\":[]}");
+        String message = "Semantic language requires exactly one eligible 
expert";
+        response.put("defaultErrorCode", code);
+        response.put("defaultError", message);
+        assertEquals(0, respond(new CamelSemantic(main()), r -> response));
+        assertTrue(printer.getOutput().contains("Default expert error: " + 
message), printer.getOutput());
+    }
+
     @ParameterizedTest
     @ValueSource(strings = {
             "Unknown expert or bean does not implement SemanticAdapter: 
missing",
@@ -130,6 +151,7 @@ class SemanticCommandTest {
     @Test
     void emitsMetadataAsOneJsonDocumentIncludingEmptyLists() throws Exception {
         JsonObject response = json("{\"evaluations\":[],\"experts\":[]}");
+        response.put("defaultErrorCode", "default_expert_error");
         response.put("defaultError", "Unknown expert or bean does not 
implement SemanticAdapter: missing");
         assertEquals(0, respond(new CamelSemantic(main()), r -> response, 
"--json"));
         assertEquals(response, json(printer.getOutput()));

Reply via email to