fix: properly serialize error objects in transcript logging (#427)
Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -945,18 +945,26 @@ export default function App({
|
||||
// Also tracks the error in telemetry so we know an error was shown
|
||||
const appendError = useCallback(
|
||||
(message: string, skipTelemetry = false) => {
|
||||
// Defensive: ensure message is always a string (guards against [object Object])
|
||||
const text =
|
||||
typeof message === "string"
|
||||
? message
|
||||
: message != null
|
||||
? JSON.stringify(message)
|
||||
: "[Unknown error]";
|
||||
|
||||
const id = uid("err");
|
||||
buffersRef.current.byId.set(id, {
|
||||
kind: "error",
|
||||
id,
|
||||
text: message,
|
||||
text,
|
||||
});
|
||||
buffersRef.current.order.push(id);
|
||||
refreshDerived();
|
||||
|
||||
// Track error in telemetry (unless explicitly skipped for user-initiated actions)
|
||||
if (!skipTelemetry) {
|
||||
telemetry.trackError("ui_error", message, "error_display", {
|
||||
telemetry.trackError("ui_error", text, "error_display", {
|
||||
modelId: currentModelId || undefined,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -420,12 +420,19 @@ export function onChunk(b: Buffers, chunk: LettaStreamingResponse) {
|
||||
for (const toolReturn of toolReturns) {
|
||||
const toolCallId = toolReturn.tool_call_id;
|
||||
// Handle both func_response (streaming) and tool_return (SDK) properties
|
||||
const resultText =
|
||||
const rawResult =
|
||||
("func_response" in toolReturn
|
||||
? toolReturn.func_response
|
||||
: undefined) ||
|
||||
("tool_return" in toolReturn ? toolReturn.tool_return : undefined) ||
|
||||
"";
|
||||
("tool_return" in toolReturn ? toolReturn.tool_return : undefined);
|
||||
|
||||
// Ensure resultText is always a string (guard against SDK returning objects)
|
||||
const resultText =
|
||||
typeof rawResult === "string"
|
||||
? rawResult
|
||||
: rawResult != null
|
||||
? JSON.stringify(rawResult)
|
||||
: "";
|
||||
const status = toolReturn.status;
|
||||
|
||||
// Look up the line by toolCallId
|
||||
|
||||
@@ -98,7 +98,29 @@ export function formatErrorDetails(e: unknown, agentId?: string): string {
|
||||
return e.message;
|
||||
}
|
||||
|
||||
// Fallback for any other type
|
||||
// Fallback for any other type (e.g., plain objects thrown by SDK or other code)
|
||||
if (typeof e === "object" && e !== null) {
|
||||
const obj = e as Record<string, unknown>;
|
||||
|
||||
// Check common error-like properties
|
||||
if (typeof obj.message === "string") {
|
||||
return obj.message;
|
||||
}
|
||||
if (typeof obj.error === "string") {
|
||||
return obj.error;
|
||||
}
|
||||
if (typeof obj.detail === "string") {
|
||||
return obj.detail;
|
||||
}
|
||||
|
||||
// Last resort: JSON stringify
|
||||
try {
|
||||
return JSON.stringify(e, null, 2);
|
||||
} catch {
|
||||
return "[Error: Unable to serialize error object]";
|
||||
}
|
||||
}
|
||||
|
||||
return String(e);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user