frontend/src/lib/utils.ts:22-28:
export function formatBytes(bytes: number): string {
if (bytes === 0) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`
}
Two edge cases:
formatBytes(1024 ** 5) // i = 5, sizes[5] = undefined → "1.0 undefined"
formatBytes(-1) // Math.log(-1) = NaN, i = NaN, sizes[NaN] = undefined → "NaN undefined"
formatBytes(NaN) // same as above
formatBytes(0.5) // i = -1, sizes[-1] = undefined → "0.5 undefined"
This is mostly cosmetic but it shows up in frontend/src/pages/System/Metrics.tsx (renders artifact sizes from Artifact.sizeBytes defined in frontend/src/lib/api/jobs.ts:59), so a corrupt size from the backend produces a NaN undefined cell, which then breaks the table header alignment in frontend/src/components/experiments/MetricsTable.tsx.
Fix
export function formatBytes(bytes: number): string {
if (!Number.isFinite(bytes) || bytes < 0) return '–'
if (bytes === 0) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1)
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`
}
frontend/src/lib/utils.ts:22-28:Two edge cases:
This is mostly cosmetic but it shows up in
frontend/src/pages/System/Metrics.tsx(renders artifact sizes fromArtifact.sizeBytesdefined infrontend/src/lib/api/jobs.ts:59), so a corrupt size from the backend produces aNaN undefinedcell, which then breaks the table header alignment infrontend/src/components/experiments/MetricsTable.tsx.Fix