@@ -87,6 +87,15 @@ struct SchemaField: Identifiable, Codable, Hashable, Sendable {
8787 }
8888}
8989
90+/// Formats a byte count that may arrive from the server as a fractional or
91+/// out-of-range Double. `Int64(_:)` from a `Double` is a *trapping* conversion —
92+/// it crashes on NaN, infinity, or values outside `Int64`'s range — so a valid
93+/// but huge JSON number like `1e30` would crash the whole decode. Guard first.
94+private func formatByteSize(_ value: Double) -> String? {
95+ guard value.isFinite, value >= 0, value < 9.223372036854776e18 else { return nil }
96+ return ByteCountFormatter.string(fromByteCount: Int64(value), countStyle: .file)
97+}
98+
9099struct StreamStats: Codable, Sendable {
91100 let ingestion: IngestionStats?
92101 let storage: StorageStats?
@@ -111,7 +120,7 @@ struct StreamStats: Codable, Sendable {
111120 } else if let n = try? container.decode(Int.self, forKey: .size) {
112121 self.size = ByteCountFormatter.string(fromByteCount: Int64(n), countStyle: .file)
113122 } else if let d = try? container.decode(Double.self, forKey: .size) {
114− self.size = ByteCountFormatter.string(fromByteCount: Int64(d), countStyle: .file)
123+ self.size = formatByteSize(d)
115124 } else {
116125 self.size = nil
117126 }
@@ -120,7 +129,7 @@ struct StreamStats: Codable, Sendable {
120129 } else if let n = try? container.decode(Int.self, forKey: .lifetime_size) {
121130 self.lifetime_size = ByteCountFormatter.string(fromByteCount: Int64(n), countStyle: .file)
122131 } else if let d = try? container.decode(Double.self, forKey: .lifetime_size) {
123− self.lifetime_size = ByteCountFormatter.string(fromByteCount: Int64(d), countStyle: .file)
132+ self.lifetime_size = formatByteSize(d)
124133 } else {
125134 self.lifetime_size = nil
126135 }
@@ -144,7 +153,7 @@ struct StreamStats: Codable, Sendable {
144153 } else if let n = try? container.decode(Int.self, forKey: .size) {
145154 self.size = ByteCountFormatter.string(fromByteCount: Int64(n), countStyle: .file)
146155 } else if let d = try? container.decode(Double.self, forKey: .size) {
147− self.size = ByteCountFormatter.string(fromByteCount: Int64(d), countStyle: .file)
156+ self.size = formatByteSize(d)
148157 } else {
149158 self.size = nil
150159 }
@@ -153,7 +162,7 @@ struct StreamStats: Codable, Sendable {
153162 } else if let n = try? container.decode(Int.self, forKey: .lifetime_size) {
154163 self.lifetime_size = ByteCountFormatter.string(fromByteCount: Int64(n), countStyle: .file)
155164 } else if let d = try? container.decode(Double.self, forKey: .lifetime_size) {
156− self.lifetime_size = ByteCountFormatter.string(fromByteCount: Int64(d), countStyle: .file)
165+ self.lifetime_size = formatByteSize(d)
157166 } else {
158167 self.lifetime_size = nil
159168 }