diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_cost_results.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_cost_results.tsx index 0965a153a4c..624c297f266 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_cost_results.tsx +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_cost_results.tsx @@ -113,10 +113,13 @@ const MultiCostResults: React.FC = ({ multiResult, timePe const validEntries = multiResult.entries.filter((e) => e.result !== null); const loadingEntries = multiResult.entries.filter((e) => e.loading); + const errorEntries = multiResult.entries.filter((e) => e.error !== null); const hasAnyResult = validEntries.length > 0; const isAnyLoading = loadingEntries.length > 0; + const hasAnyError = errorEntries.length > 0; - if (!hasAnyResult && !isAnyLoading) { + // Show empty state only if no results, not loading, and no errors + if (!hasAnyResult && !isAnyLoading && !hasAnyError) { return (
@@ -126,7 +129,8 @@ const MultiCostResults: React.FC = ({ multiResult, timePe ); } - if (!hasAnyResult && isAnyLoading) { + // Show loading state only if loading and no results/errors yet + if (!hasAnyResult && isAnyLoading && !hasAnyError) { return (
} /> @@ -135,6 +139,26 @@ const MultiCostResults: React.FC = ({ multiResult, timePe ); } + // Show errors-only view when there are errors but no valid results + if (!hasAnyResult && hasAnyError) { + return ( +
+ +
+ Cost Estimates + {isAnyLoading && } size="small" />} +
+ {/* Error Messages */} + {errorEntries.map((e) => ( +
+ {e.entry.model || "Unknown model"}: + {e.error} +
+ ))} +
+ ); + } + const toggleExpanded = (id: string) => { setExpandedModels((prev) => { const next = new Set(prev); @@ -157,13 +181,28 @@ const MultiCostResults: React.FC = ({ multiResult, timePe title: "Model", dataIndex: "model", key: "model", - render: (text: string, record: { id: string; provider?: string | null }) => ( -
- {text} - {record.provider && ( - - {record.provider} - + render: (text: string, record: { id: string; provider?: string | null; error?: string | null; loading?: boolean; hasZeroCost?: boolean }) => ( +
+
+ {text} + {record.provider && ( + + {record.provider} + + )} + {record.loading && ( + } size="small" /> + )} +
+ {record.error && ( +
+ ⚠️ {record.error} +
+ )} + {record.hasZeroCost && !record.error && ( +
+ ⚠️ No pricing data found for this model. Set base_model in config. +
)}
), @@ -173,17 +212,21 @@ const MultiCostResults: React.FC = ({ multiResult, timePe dataIndex: "cost_per_request", key: "cost_per_request", align: "right" as const, - render: (value: number) => {formatCost(value)}, + render: (value: number | null, record: { error?: string | null }) => ( + record.error ? - : {formatCost(value)} + ), }, { title: "Margin Fee", dataIndex: "margin_cost_per_request", key: "margin_cost_per_request", align: "right" as const, - render: (value: number) => ( - 0 ? "text-amber-600" : "text-gray-400"}`}> - {formatCost(value)} - + render: (value: number | null, record: { error?: string | null }) => ( + record.error ? - : ( + 0 ? "text-amber-600" : "text-gray-400"}`}> + {formatCost(value)} + + ) ), }, { @@ -191,34 +234,43 @@ const MultiCostResults: React.FC = ({ multiResult, timePe dataIndex: periodCostKey, key: "period_cost", align: "right" as const, - render: (value: number | null) => {formatCost(value)}, + render: (value: number | null, record: { error?: string | null }) => ( + record.error ? - : {formatCost(value)} + ), }, { title: "", key: "expand", width: 40, - render: (_: unknown, record: { id: string }) => ( - + render: (_: unknown, record: { id: string; error?: string | null }) => ( + record.error ? null : ( + + ) ), }, ]; - const summaryData = validEntries.map((e) => ({ + // Include both valid results and errors in the table data + const allEntriesWithModels = multiResult.entries.filter((e) => e.entry.model); + const summaryData = allEntriesWithModels.map((e) => ({ key: e.entry.id, id: e.entry.id, - model: e.result!.model, - provider: e.result!.provider, - cost_per_request: e.result!.cost_per_request, - margin_cost_per_request: e.result!.margin_cost_per_request, - daily_cost: e.result!.daily_cost, - monthly_cost: e.result!.monthly_cost, + model: e.result?.model || e.entry.model, + provider: e.result?.provider, + cost_per_request: e.result?.cost_per_request ?? null, + margin_cost_per_request: e.result?.margin_cost_per_request ?? null, + daily_cost: e.result?.daily_cost ?? null, + monthly_cost: e.result?.monthly_cost ?? null, + error: e.error, + loading: e.loading, + hasZeroCost: e.result && e.result.cost_per_request === 0, })); return ( @@ -268,7 +320,7 @@ const MultiCostResults: React.FC = ({ multiResult, timePe {/* Per-Model Table */} - {validEntries.length > 0 && ( + {summaryData.length > 0 && ( = ({ multiResult, timePe }} /> )} - - {/* Error Messages */} - {multiResult.entries - .filter((e) => e.error) - .map((e) => ( -
- {e.entry.model || "Unknown model"}: - {e.error} -
- ))} ); };