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
Summary
--build-overviewshas been broken since 3.6.0. A missing space between two adjacentstring literals in
opendm/orthophoto.pymakesgdaladdoreceive the orthophoto path asthe value of
--config PHOTOMETRIC_OVERVIEW, so it then treats2as its input raster andexits non-zero.
system.runraisesSubprocessException, so the run aborts atodm_orthophotorather than degrading.Root cause
opendm/orthophoto.py,build_overviews()(lines 37–42 on master):Python concatenates adjacent literals at compile time, so the command becomes:
The path is consumed as the config value, leaving
2as the first positional argument —i.e. the dataset gdaladdo tries to open.
Note the preceding
INTERLEAVE_OVERVIEW PIXELline does have its trailing space; only thePHOTOMETRIC_OVERVIEWline 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.pyhas had no commits since that date, so master is still affected.Affected versions
PHOTOMETRIC_OVERVIEWnot present)Reproduction
Any georeferenced reconstruction that reaches
post_orthophoto_stepswith--build-overviewsand without--cog:stages/odm_orthophoto.pycallspost_orthophoto_steps(), which runsbuild_overviews()under
if args.build_overviews and not args.cog. The failure lands at the end of thepipeline, after SfM and MVS have already completed, so it is an expensive way to fail.
Suggested fix
One character:
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 ofremembering 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