summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVachan <[email protected]>2025-06-27 16:57:40 -0700
committerGitHub <[email protected]>2025-06-27 23:57:40 +0000
commitdb115c468a894e7bf203e18577f1b698e939aef0 (patch)
tree2c102015312e2eb07d955ddc41ed55059e3abd18
parent150df382f8e0b84aa6028622480c28186c99b8a7 (diff)
Updates error handling in case of incorrect tool calling. (#2304)
-rw-r--r--packages/cli/src/nonInteractiveCli.test.ts65
-rw-r--r--packages/cli/src/nonInteractiveCli.ts7
2 files changed, 71 insertions, 1 deletions
diff --git a/packages/cli/src/nonInteractiveCli.test.ts b/packages/cli/src/nonInteractiveCli.test.ts
index 54d57ae2..01ef5782 100644
--- a/packages/cli/src/nonInteractiveCli.test.ts
+++ b/packages/cli/src/nonInteractiveCli.test.ts
@@ -218,4 +218,69 @@ describe('runNonInteractive', () => {
'[API Error: API connection failed]',
);
});
+
+ it('should not exit if a tool is not found, and should send error back to model', async () => {
+ const functionCall: FunctionCall = {
+ id: 'fcNotFound',
+ name: 'nonExistentTool',
+ args: {},
+ };
+ const errorResponsePart: Part = {
+ functionResponse: {
+ name: 'nonExistentTool',
+ id: 'fcNotFound',
+ response: { error: 'Tool "nonExistentTool" not found in registry.' },
+ },
+ };
+
+ const { executeToolCall: mockCoreExecuteToolCall } = await import(
+ '@google/gemini-cli-core'
+ );
+ vi.mocked(mockCoreExecuteToolCall).mockResolvedValue({
+ callId: 'fcNotFound',
+ responseParts: [errorResponsePart],
+ resultDisplay: 'Tool "nonExistentTool" not found in registry.',
+ error: new Error('Tool "nonExistentTool" not found in registry.'),
+ });
+
+ const stream1 = (async function* () {
+ yield { functionCalls: [functionCall] } as GenerateContentResponse;
+ })();
+ const stream2 = (async function* () {
+ yield {
+ candidates: [
+ {
+ content: {
+ parts: [{ text: 'Unfortunately the tool does not exist.' }],
+ },
+ },
+ ],
+ } as GenerateContentResponse;
+ })();
+ mockChat.sendMessageStream
+ .mockResolvedValueOnce(stream1)
+ .mockResolvedValueOnce(stream2);
+ const consoleErrorSpy = vi
+ .spyOn(console, 'error')
+ .mockImplementation(() => {});
+
+ await runNonInteractive(mockConfig, 'Trigger tool not found');
+
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
+ 'Error executing tool nonExistentTool: Tool "nonExistentTool" not found in registry.',
+ );
+
+ expect(mockProcessExit).not.toHaveBeenCalled();
+
+ expect(mockChat.sendMessageStream).toHaveBeenCalledTimes(2);
+ expect(mockChat.sendMessageStream).toHaveBeenLastCalledWith(
+ expect.objectContaining({
+ message: [errorResponsePart],
+ }),
+ );
+
+ expect(mockProcessStdoutWrite).toHaveBeenCalledWith(
+ 'Unfortunately the tool does not exist.',
+ );
+ });
});
diff --git a/packages/cli/src/nonInteractiveCli.ts b/packages/cli/src/nonInteractiveCli.ts
index 95a9c51c..64a87162 100644
--- a/packages/cli/src/nonInteractiveCli.ts
+++ b/packages/cli/src/nonInteractiveCli.ts
@@ -110,10 +110,15 @@ export async function runNonInteractive(
);
if (toolResponse.error) {
+ const isToolNotFound = toolResponse.error.message.includes(
+ 'not found in registry',
+ );
console.error(
`Error executing tool ${fc.name}: ${toolResponse.resultDisplay || toolResponse.error.message}`,
);
- process.exit(1);
+ if (!isToolNotFound) {
+ process.exit(1);
+ }
}
if (toolResponse.responseParts) {