summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/utils/errorParsing.ts
diff options
context:
space:
mode:
authorScott Densmore <[email protected]>2025-06-07 22:04:57 -0700
committerGitHub <[email protected]>2025-06-07 22:04:57 -0700
commitb46f22093145760eaf8cefafd0050597bfb44249 (patch)
treeeeb3eb26e2289c1d5feef272745c105a2dbfca93 /packages/cli/src/ui/utils/errorParsing.ts
parent6e4b84a60d0f94ba772b9872385d1c4021090786 (diff)
feat(cli): improve API error parsing and display (#829)
Diffstat (limited to 'packages/cli/src/ui/utils/errorParsing.ts')
-rw-r--r--packages/cli/src/ui/utils/errorParsing.ts56
1 files changed, 56 insertions, 0 deletions
diff --git a/packages/cli/src/ui/utils/errorParsing.ts b/packages/cli/src/ui/utils/errorParsing.ts
new file mode 100644
index 00000000..aec337b6
--- /dev/null
+++ b/packages/cli/src/ui/utils/errorParsing.ts
@@ -0,0 +1,56 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export interface ApiError {
+ error: {
+ code: number;
+ message: string;
+ status: string;
+ details: unknown[];
+ };
+}
+
+function isApiError(error: unknown): error is ApiError {
+ return (
+ typeof error === 'object' &&
+ error !== null &&
+ 'error' in error &&
+ typeof (error as ApiError).error === 'object' &&
+ 'message' in (error as ApiError).error
+ );
+}
+
+export function parseAndFormatApiError(errorMessage: string): string {
+ // The error message might be prefixed with some text, like "[Stream Error: ...]".
+ // We want to find the start of the JSON object.
+ const jsonStart = errorMessage.indexOf('{');
+ if (jsonStart === -1) {
+ return errorMessage; // Not a JSON error, return as is.
+ }
+
+ const jsonString = errorMessage.substring(jsonStart);
+
+ try {
+ const error = JSON.parse(jsonString) as unknown;
+ if (isApiError(error)) {
+ let finalMessage = error.error.message;
+ try {
+ // See if the message is a stringified JSON with another error
+ const nestedError = JSON.parse(finalMessage) as unknown;
+ if (isApiError(nestedError)) {
+ finalMessage = nestedError.error.message;
+ }
+ } catch (_e) {
+ // It's not a nested JSON error, so we just use the message as is.
+ }
+ return `API Error: ${finalMessage} (Status: ${error.error.status})`;
+ }
+ } catch (_e) {
+ // Not a valid JSON, fall through and return the original message.
+ }
+
+ return errorMessage;
+}