Skip to content

fails to read right-edge tiles with scale=0.0001 in UInt16 COGs #534

Description

@pieterjandebruyne

Summary

geotiff.js v2.1.3 fails when reading right-edge tiles in UInt16 COG files with scale=0.0001, but works fine with:

  • Float32 data type (same tile structure)
  • UInt16 without scale/offset metadata
  • UInt16 with larger scale values (0.1, 0.01, 0.001)

Error: TypeError: Cannot read properties of undefined (reading 'offset')
Location: BlockedSource.readSliceData line 3592

I did several tests across multiple files, you can find a summary of my findings structured by an llm underneath. Feel free to ask me additional questions about my setup etc.
might be related to #531

Environment

  • geotiff.js: 2.1.3
  • Image: 650×400px, 224 bands, DEFLATE, 64×64 tiles, COG with overviews
  • Affected tiles: Right edge (x ≥ 640), partial tiles 640-650

Reproduction

Test with different scale values

We tested UInt16 COG files with identical structure but different scale/offset metadata:

Configuration Scale Right-edge tiles work?
Float32 (no scale) N/A ✅ Works
UInt16 unscaled N/A ✅ Works
UInt16 scale=0.1 0.1 ✅ Works
UInt16 scale=0.01 0.01 ✅ Works
UInt16 scale=0.001 0.001 ✅ Works
UInt16 scale=0.0001 0.0001 ❌ Fails

Finding: Issue only occurs with scale=0.0001 (multiplier 10,000), not other scale values.

Failing vs working windows

Windows including right-edge tiles (x ≥ 640) fail only with scale=0.0001:

Window Description Result
[542, 0, 642, 100] Right edge ❌ Fails
[633, 8, 643, 18] Crosses x=640 ❌ Fails
[600, 0, 650, 50] To boundary ❌ Fails
[550, 350, 650, 400] Bottom-right ❌ Fails
[0, 350, 100, 400] Bottom-left ✅ Works
[275, 350, 375, 400] Middle-bottom ✅ Works
[0, 0, 100, 100] Interior ✅ Works

Pattern: Only right-edge fails, bottom/left edges work fine.

Code to reproduce

import { fromUrl } from 'geotiff';

const url = 'https://example.com/uint16-scale0.0001.tif';

const tiff = await fromUrl(url);
const image = await tiff.getImage();

// Fails with scale=0.0001, works with 0.001 or larger
const rasters = await image.readRasters({
  window: [542, 0, 642, 100],  // Right-edge window
  fillValue: 0
});
// TypeError: Cannot read properties of undefined (reading 'offset')

Stack trace

TypeError: Cannot read properties of undefined (reading 'offset')
    at geotiff.js:3603:29
    at Array.map (<anonymous>)
    at BlockedSource.readSliceData (geotiff.js:3592:19)
    at BlockedSource.fetch (geotiff.js:3507:17)
    at async GeoTIFFImage.getTileOrStrip (geotiff.js:2141:20)
    at async GeoTIFFImage._readRaster (geotiff.js:2260:5)
    at async GeoTIFFImage.readRasters (geotiff.js:2351:20)

File metadata (via gdalinfo)

Working: UInt16 with scale=0.001

Band 1 Block=64x64 Type=UInt16
  Offset: 0,   Scale:0.001

Failing: UInt16 with scale=0.0001

Band 1 Block=64x64 Type=UInt16
  Offset: 0,   Scale:0.0001

All files validated as proper COGs with GDAL and read correctly by rasterio.

Analysis

The issue is specifically triggered by:

  1. UInt16 data type (not Float32)
  2. Scale value of 0.0001 (not 0.001 or larger)
  3. Right-edge partial tiles (not bottom/left edges)

Hypothesis

The scale value 0.0001 may trigger a precision or rounding issue in tile offset calculations, causing undefined lookups in the tile offset table specifically for right-edge tiles. This could be:

  • Floating-point precision error in offset arithmetic
  • Scale-dependent tile boundary calculation bug
  • Edge tile offset table indexing issue with small scale values

Bottom/left edges work because they likely use different code paths or tile ordering.

Additional info

All test files have identical structure (compression, tile size, dimensions, overviews) and differ only in scale metadata value. Files can be provided for debugging if needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugReports a bug or error

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions