Skip to content

[Bug] --build-overviews fails since 3.6.0: missing space concatenates the orthophoto path into --config PHOTOMETRIC_OVERVIEW #2058

Description

@jousby

Summary

--build-overviews has been broken since 3.6.0. A missing space between two adjacent
string literals in opendm/orthophoto.py makes gdaladdo receive the orthophoto path as
the value of --config PHOTOMETRIC_OVERVIEW, so it then treats 2 as its input raster and
exits non-zero. system.run raises SubprocessException, so the run aborts at
odm_orthophoto rather than degrading.

Root cause

opendm/orthophoto.py, build_overviews() (lines 37–42 on master):

system.run('gdaladdo -r average '
            '--config BIGTIFF_OVERVIEW IF_SAFER '
            '--config COMPRESS_OVERVIEW JPEG '
            '--config INTERLEAVE_OVERVIEW PIXEL '
            '--config PHOTOMETRIC_OVERVIEW YCBCR'      # <-- no trailing space
            '{orthophoto} 2 4 8 16'.format(**kwargs))

Python concatenates adjacent literals at compile time, so the command becomes:

gdaladdo -r average --config BIGTIFF_OVERVIEW IF_SAFER --config COMPRESS_OVERVIEW JPEG \
  --config INTERLEAVE_OVERVIEW PIXEL \
  --config PHOTOMETRIC_OVERVIEW YCBCR/path/to/odm_orthophoto/odm_orthophoto.tif 2 4 8 16

The path is consumed as the config value, leaving 2 as the first positional argument —
i.e. the dataset gdaladdo tries to open.

Note the preceding INTERLEAVE_OVERVIEW PIXEL line does have its trailing space; only the
PHOTOMETRIC_OVERVIEW line is missing one.

Introduced by

#1935 ("Add interleave=pixel and photometric=ycbcr for orthophoto overviews by default",
merged 2025-10-07). The diff adds both lines, with the space present on the first and absent
on the second.

opendm/orthophoto.py has had no commits since that date, so master is still affected.

Affected versions

  • 3.5.6 — not affected (PHOTOMETRIC_OVERVIEW not present)
  • 3.6.0, 3.6.1 — affected
  • master — affected

Reproduction

Any georeferenced reconstruction that reaches post_orthophoto_steps with
--build-overviews and without --cog:

docker run -ti --rm -v /path/to/project:/datasets/code opendronemap/odm:3.6.1 \
  --project-path /datasets --build-overviews --dsm

stages/odm_orthophoto.py calls post_orthophoto_steps(), which runs build_overviews()
under if args.build_overviews and not args.cog. The failure lands at the end of the
pipeline, after SfM and MVS have already completed, so it is an expensive way to fail.

Suggested fix

One character:

-                '--config PHOTOMETRIC_OVERVIEW YCBCR'
+                '--config PHOTOMETRIC_OVERVIEW YCBCR '
                 '{orthophoto} 2 4 8 16'.format(**kwargs))

Happy to open a PR if that is useful — it seemed more polite to report first in case you
would rather fix it alongside something else in that function.

A guard against the general case might also be worth it: every argument in this call is
built by literal concatenation, so the same omission is easy to reintroduce. Building the
argument list and joining on ' ' would make it structural rather than a matter of
remembering the trailing space.

How this was found

Noticed while auditing a pinned ODM version for an upgrade — a GPU image had drifted from
3.5.6 to 3.6.1 via a floating tag, and the difference surfaced as orthophoto-stage failures
on jobs that request DEM output without COG. Not a synthetic case

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions