Skip to content

fix(db,ui,docs): an unknown size is absent, not zero, and a share needs a total - #517

Merged
cevheri merged 2 commits into
mainfrom
fix/absent-size-not-zero
Aug 27, 2026
Merged

fix(db,ui,docs): an unknown size is absent, not zero, and a share needs a total#517
cevheri merged 2 commits into
mainfrom
fix/absent-size-not-zero

Conversation

@cevheri

@cevheri cevheri commented Aug 27, 2026

Copy link
Copy Markdown
Member

Closes the producer side and the consumer side of one defect: an unknown database size reaching a
reader as a confident zero. Three backlog entries close (D44 in part, D46, U24) and four open in their
place (D50, D51, U25, U26), each measured rather than inferred.

What was wrong

Two providers stated both facts in one object. Trino paired databaseSize: TRINO_UNAVAILABLE_TEXT
with databaseSizeBytes: 0; the search seam paired SEARCH_UNKNOWN_TEXT with sizeBytes ?? 0. The
string said "unavailable" and the number said "zero bytes", from the same input. Both now omit the key,
which is what the optional field is for, and a real zero still reads as zero.

The search seam held the last unconditional activeConnections: 0 (D46). It is absent now, and
getHealth() stops composing a key it has no source for.

The Storage tab divided by a total it did not have. Three figures were affected, not the one the
entry named:

  • the remainder bar was drawn FULL over a zero-byte database - 100 - 0 - 0 - and nothing numeric was
    wrong, so no text assertion could see it;
  • the Tables and Indexes percentages rendered 0.0% under real megabyte figures, a fabricated
    denominator under an honest numerator;
  • the remainder's BYTES rendered -943718400 B when a measured-zero total met per-table reads that
    answered, because getTableStats() is a separate read that does not share the overview's failure.

A share now requires totalSize > 0, which excludes the absent size and the measured zero alike, so one
test covers both. The remainder's bytes are gated on the CONTRADICTION instead, deliberately not on the
share: 0 - 0 - 0 is an honest zero and stays one.

A refused overview lost the engine's sentence in a file that surfaces it for two sibling panels. It
has one now.

The shared formatBytes refused nothing. Measured live: -1, NaN and both infinities all
rendered "NaN undefined", and a petabyte rendered "1 undefined" - a number wearing a missing unit,
which scans as a figure rather than as garbage. Non-magnitudes return "N/A", the ladder gains PB and
EB, and the index is CLAMPED, which makes indexing past the array unreachable rather than moving the
boundary up two rungs.

Three claims this repo made about itself, corrected

The backlog entry, docs/providers/mongodb.md and a mongodb.ts comment all said the negative
remainder renders NaN undefined. It does not. StorageTab defines its OWN local byte formatter and
never imports the shared one, so the cell renders -1536 B. A review lane had reported exactly that in
the previous round and was overruled by a measurement of the wrong function.

The search docs asserted that TableStats "has no way to say unknown - both fields are required
numbers". Measured against types.ts: rowCount, totalSize and totalSizeBytes are required;
tableSize, tableSizeBytes, indexSize and indexSizeBytes are optional, and their own docblock
argues for absence. Corrected here; the code half is D50.

A new comment claimed the search provider held "the last zero". It held the last unconditional literal
one. Four providers still reach a zero by a longer route, which is D51.

New entries, all measured

  • D50 - the search seam zeroes two OPTIONAL TableStats size fields for a closed index. Not fixed
    here because omitting them takes the Data figure away from every open index in the cluster
    (tables.every(...)), which is a visible panel change and wants its own decision.
  • D51 - Trino, Druid, ClickHouse and Couchbase each degrade a refused monitoring read to no rows and
    then map the absent row to 0. ClickHouse's does it to six fields at once, so one refused read
    publishes a fully-zeroed overview that reads as measured.
  • U25 - formatBytes exists three times; the two component-local copies have no guard and render
    -1 B, NaN B, Infinity GB.
  • U26 - the admin fleet total re-parses formatted strings and has no tb branch, so a 1 TB database
    contributes 1 byte. The real defect is that FleetHealthItem carries no numeric channel at all.

Verification

  • Six local gates green; coverage 100%.
  • Every lane's work was reviewed adversarially, and four review findings were verified before adoption -
    one of them enlarged (Trino belonged in D51 and the reviewer had not measured it), one narrowed.
  • Non-vacuity proven by mutation for each new guard: reverting remainderKnown's non-negative check,
    the Quick Stats gate, and the three *Unavailable guards' === undefined half each turns the suite
    RED. That last one is a guard shape that had existed for two rounds with nothing pinning it.
  • A second test file the triad invariant does not name - tests/unit/db/trino/introspect.test.ts -
    asserted the old 0. Only a test run found it.

…ds a total

Two providers stated both facts in one object. Trino paired
`databaseSize: TRINO_UNAVAILABLE_TEXT` with `databaseSizeBytes: 0`, and the search
seam paired `SEARCH_UNKNOWN_TEXT` with `sizeBytes ?? 0`, so one overview said
"unavailable" in the string and "zero bytes" in the number from a single input.
Both now omit the key, which is what the optional field is for, and a real zero
still reads as zero. Apache Cassandra had already written the argument down.

The search seam also held the last unconditional `activeConnections: 0`. It is
absent now, and `getHealth()` stops composing a key it has no source for. Not the
last zero of any kind: Trino, Druid, ClickHouse and Couchbase each degrade a
refused monitoring read to no rows and then map the absent row to zero, which is
the same encoding by a longer route and is filed rather than fixed here.

The Storage tab is where the fabrications were visible, and three of its figures
divided by a total it did not have. A share now requires `totalSize > 0`, which
excludes the absent size and the measured zero alike, so the remainder bar is empty
instead of full and the two Quick Stats percentages no longer sit under real
megabyte figures. The remainder's BYTES are gated on the contradiction rather than
on the share: a 0 total beside per-table reads that answered rendered a negative
byte count, while `0 - 0 - 0` is an honest zero and stays one. A refused overview
now carries the engine's own sentence, the way two sibling panels do.

Verified end to end in Chrome against the SQLite sample: unpatched, the breakdown
reads 504 + 288 + 4 = 796 KB with bars at -36.68% / -63.82% / -99.4975%; with the
overview's size forced to 0 while the table read answers, the remainder reads N/A,
all three bars are empty, and no percentage is drawn anywhere.

The shared `formatBytes` refused nothing. Measured live: -1, NaN and both
infinities all rendered "NaN undefined", and a petabyte rendered "1 undefined" - a
number wearing a missing unit, which scans as a figure rather than as garbage.
Non-magnitudes return "N/A", the string three other places in this codebase
already use for a size they do not have; the ladder gains PB and EB; and the index
is clamped, which makes indexing past the array unreachable rather than moving the
boundary up two rungs.

Also corrects three claims this repo made about itself. The Storage tab defines its
own local byte formatter and never imports the shared one, so the negative
remainder rendered "-1536 B" and not "NaN undefined" as mongodb.md, a mongodb.ts
comment and the backlog entry all said - a review lane reported exactly that last
round and was overruled by a measurement of the wrong function. The search docs'
claim that `TableStats` cannot say "unknown" is false for its four optional size
fields. And a new comment claiming the last zero anywhere was narrowed to the last
unconditional one.
D46 and U24 close outright. D44 closes three of its fourteen type-ids - the ones
that contradicted themselves inside a single object - and its counts moved for a
second reason: DuckDB arrived as a seventeenth type-id in #516 and already writes
the key conditionally, so it is a fourth correct provider rather than a fifteenth
fabricating one. The title now reads 11 of 17, the remaining-work list names all
eleven files, and MongoDB is explicitly off that list because both its paths were
already right.

Four entries open, each measured rather than inferred:

D50 - the search seam zeroes two OPTIONAL `TableStats` size fields for a closed
index. Not fixed alongside the rest because omitting them takes the Data figure
away from every open index in the cluster, through `tables.every(...)`, which is a
visible panel change that wants its own decision rather than a drive-by.

D51 - Trino, Druid, ClickHouse and Couchbase each swallow an unavailable
monitoring surface into an empty result and then map the absent row to 0.
ClickHouse's does it to six fields at once, so one refused read publishes a
fully-zeroed overview that reads as measured. Filed as one entry because the fix
is one decision applied four times: the degrade step already knows the difference
and discards it before the mapper can act. Redis and PostgreSQL are named as NOT
measured rather than folded in on resemblance.

U25 - `formatBytes` exists three times, and the two component-local copies have no
guard: measured, they render "-1 B", "NaN B", "Infinity GB" and an exabyte in
gigabytes.

U26 - the admin fleet total re-parses formatted strings and has no `tb` branch, so
a 1 TB database contributes one byte, and this round's PB and EB rungs add two more
spellings that land in the same arm. The real defect is that `FleetHealthItem`
carries no numeric channel at all, which is also what makes an honest absence
inexpressible there.

The section index lines were recomputed from the surviving headings rather than
merged. Both new ids had to move: this branch took D47 and D48 before #516 merged
and published its own, and the bodies auto-merged without a conflict while only the
index line reported one - the same mechanism as #513, caught this time by the guard
#514 added.
@sonarqubecloud

Copy link
Copy Markdown

@cevheri
cevheri merged commit 2803ae8 into main Aug 27, 2026
22 checks passed
@cevheri
cevheri deleted the fix/absent-size-not-zero branch August 27, 2026 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant