Found by the three-platform R CMD check workflow added in #52, on its first run — job log.
The claim
CLAUDE.md, a Key Decision from v0.11.0 (#23):
Output band counts do not change, because -srcalpha excludes the alpha band from the warped band list. That is what let masking default to on without moving stac_airphoto_bc.
inst/notes/border-masking.md carries the same statement, and test-fly_georef_mask.R asserts it:
expect_equal(fly_gdal_bands(fly_gdal_info(on_file)),
fly_gdal_bands(fly_gdal_info(off_file)))
expect_equal(fly_gdal_bands(fly_gdal_info(on_file)), if (bands >= 3L) 4L else 1L)
What Windows does
For a grayscale (1-band) source, masking on gives 2 bands, masking off gives 1:
── Failure ('test-fly_georef_mask.R:194:5') ──
Expected `fly_gdal_bands(fly_gdal_info(on_file))` to equal `fly_gdal_bands(fly_gdal_info(off_file))`.
`actual`: 2
`expected`: 1
ubuntu-latest and macos-latest both pass. So the invariant holds on two of the three GDAL builds and not on the third — it was measured on one platform and written down as unconditional.
The 3-band RGB case is not implicated: both arms give 4 there on every runner.
Why it matters beyond a red tick
The stated reason this invariant was worth having is that it is what let masking default to on without moving stac_airphoto_bc. If a Windows-produced grayscale GeoTIFF carries an extra band, that consumer's schema assumption is wrong for those files — silently, since an extra band is not an error anywhere.
Grayscale is also the arm with the weaker contract already (-dstnodata 0 rather than -dstalpha, fly#56), so it is the arm where a band appearing is least expected and least likely to be noticed.
What would settle it
- Which GDAL version the Windows CRAN
sf binary carries, against ubuntu-24.04's 3.8.4 and the macOS binary — this may be a version difference rather than a platform one.
- Whether
-srcalpha is being applied at all on that build for a 1-band source, or whether -dstnodata is producing the mask band.
- Then either pin the band count in
fly_georef() regardless of platform, or state the invariant conditionally and tell stac_airphoto_bc which files can carry the extra band.
Meanwhile
#52 marks the two band-count assertions as skipped on Windows, citing this issue, so the rest of that test — including the collar-removal measurements — keeps running on all three platforms. The skip is printed by that workflow's "Report skipped tests" step on every run rather than being silent.
Found by the three-platform
R CMD checkworkflow added in #52, on its first run — job log.The claim
CLAUDE.md, a Key Decision from v0.11.0 (#23):inst/notes/border-masking.mdcarries the same statement, andtest-fly_georef_mask.Rasserts it:What Windows does
For a grayscale (1-band) source, masking on gives 2 bands, masking off gives 1:
ubuntu-latest and macos-latest both pass. So the invariant holds on two of the three GDAL builds and not on the third — it was measured on one platform and written down as unconditional.
The 3-band RGB case is not implicated: both arms give 4 there on every runner.
Why it matters beyond a red tick
The stated reason this invariant was worth having is that it is what let masking default to on without moving
stac_airphoto_bc. If a Windows-produced grayscale GeoTIFF carries an extra band, that consumer's schema assumption is wrong for those files — silently, since an extra band is not an error anywhere.Grayscale is also the arm with the weaker contract already (
-dstnodata 0rather than-dstalpha, fly#56), so it is the arm where a band appearing is least expected and least likely to be noticed.What would settle it
sfbinary carries, against ubuntu-24.04's 3.8.4 and the macOS binary — this may be a version difference rather than a platform one.-srcalphais being applied at all on that build for a 1-band source, or whether-dstnodatais producing the mask band.fly_georef()regardless of platform, or state the invariant conditionally and tellstac_airphoto_bcwhich files can carry the extra band.Meanwhile
#52 marks the two band-count assertions as skipped on Windows, citing this issue, so the rest of that test — including the collar-removal measurements — keeps running on all three platforms. The skip is printed by that workflow's "Report skipped tests" step on every run rather than being silent.