Skip to content

formatBytes returns wrong unit for >= 1 PiB and crashes on negative/NaN #15

Description

@bouncia

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]}`
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions