Re: PostgreSQL MSI ignores --datadir flag during minor upgrade on Windows

From: Sandeep Thakkar <sandeep(dot)thakkar(at)enterprisedb(dot)com>
To: Ben Caspi <benc(at)aidoc(dot)com>
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org, Avi Uziel <avi(dot)uziel(at)aidoc(dot)com>, Liran Amrani <lirana(at)aidoc(dot)com>, Shahar Amram <shahara(at)aidoc(dot)com>
Subject: Re: PostgreSQL MSI ignores --datadir flag during minor upgrade on Windows
Date: 2026-02-25 16:07:36
Message-ID: CANFyU95x5LbDf-4neKNqOgQmO42Kqe+cj8kuAafh-DipsZc9eg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

On Fri, Feb 20, 2026 at 1:51 PM Ben Caspi <benc(at)aidoc(dot)com> wrote:

> Hello,
>
> Recently we tried to upgrade a client machine's PostgreSQL version from
> 15.13 to 15.16.
> We often upgrade our client machines from versions 9/13 to 15 without
> encountering any issues.
> However, during this upgrade (15.13 --> 15.16) we've noticed that
> post-upgrade the PostgreSQL service assigned data directory changed to the
> default value "C:\Program Files\PostgreSQL\15\data".
>
> Our client's data directory prior to the upgrade was
> "F:\AidocData\PostgreSQL\15\data". This change caused data to be written to
> the wrong location until we found the issue.
>
> This is the command we use for the upgrade:
>
>> Start-Process $installer_exe -ArgumentList "--unattendedmodeui minimal
>> --mode unattended --superaccount $POSTGRES_ROOT_USER --superpassword
>> $POSTGRES_ROOT_USER_PWD --serverport $port --datadir `"$data_dir`" --locale
>> `"$locale_name`"" -Wait
>
>
> I looked into your codebase and found that during an upgrade the installer
> defaults to the Registry value for data directory and ignores the --datadir
> flag I provided in my command.
>
> That behaviour is by design. The command-line options override the default
values only during the new installation. In upgrade mode, the registry
values are the source of truth for the installer.

In server/pgserver.xml.in, in the server component’s
> preInstallationActionList:
>
> *pgserver.xml.in <http://pgserver.xml.in>*
> Lines 1142-1153
>
> <!-- Set datadir if an existing installation is found -->
>> <setInstallerVariable>
>> <name>datadir</name>
>> <value>${iDataDirectory}</value>
>> <ruleList>
>> <stringTest>
>> <text>${iDataDirectory}</text>
>> <type>not_empty</type>
>> </stringTest>
>> <isFalse value="${extract_mode}"/>
>> </ruleList>
>> </setInstallerVariable>
>
>
>
> *iDataDirectory is read from the registry here:*
> *pgserver.xml.in <http://pgserver.xml.in>*
> Lines 1003-1008
>
> <!-- Get the existing data directory. -->
>> <registryGet>
>> <name>Data Directory</name>
>>
>> <key>HKEY_LOCAL_MACHINE\SOFTWARE\PostgreSQL\Installations\postgresql${service_suffix}-${product_version}</key>
>> <variable>iDataDirectory</variable>
>> </registryGet>
>
>
> *What goes wrong:*
> When passing --datadir "F:\AidocData\PostgreSQL\15\data" on the command
> line, the wizard sets datadir = "F:\AidocData\PostgreSQL\15\data".
>
> Later, in preInstallationActionList, the installer reads iDataDirectory
> from the registry.
> If iDataDirectory is not empty, it overwrites datadir with that value.
>
> 1. There is no check that the user explicitly provided --datadir, so
> the CLI value is ignored.
>
> If the registry still has the old default path (e.g. C:\Program
> Files\PostgreSQL\15\data), the service ends up re-registered with that path
> instead of F:\AidocData\PostgreSQL\15\data.
> When the registry can be wrong
>
> - Initial install used the default data directory, then data was moved
> to F:\AidocData\PostgreSQL\15\data and the service was updated manually,
> but the PostgreSQL registry key was not.
>
> This is the problem for the installer. If you change the paths later that
were given during installation, you must also change the registry key value
for the installer to know.

>
> - A previous install or reinstall wrote the default path to the
> registry.
> - Any other case where the registry value does not match the actual
> data location.
>
>
> *Fix*
> Only use the registry value when the user has not provided --datadir on
> the command line. For example, add a condition so that datadir is set from
> iDataDirectory only when datadir is empty:
>
> <!-- Set datadir if an existing installation is found (only when user
>> didn't provide --datadir) -->
>> <setInstallerVariable>
>> <name>datadir</name>
>> <value>${iDataDirectory}</value>
>> <ruleList>
>> <stringTest>
>> <text>${iDataDirectory}</text>
>> <type>not_empty</type>
>> </stringTest>
>> <stringTest>
>> <text>${datadir}</text>
>> <type>empty</type>
>> </stringTest>
>> <isFalse value="${extract_mode}"/>
>> </ruleList>
>> </setInstallerVariable>
>
>
> This keeps the current behavior when --datadir is not passed, but ensures
> that an explicit --datadir is not overridden by the registry.
>
> Thanks, but this change in behaviour constitutes a design change and
should probably also apply to other options. We'll evaluate this further.
But for now, the fix is to update your registry keys to deflect the change
you made to the datadir.

> Please consider investigating this issue and its solution.
> If I misunderstood anything please let me know. Thanks!
> --
>
> [image: photo]
>
> Ben Caspi
> DevOps Engineer
>
> www.aidoc.com | benc(at)aidoc(dot)com
>
> [image: linkedin] <https://www.linkedin.com/company/aidoc/>
>
> [image: twitter] <https://twitter.com/aidocmed>
>
> [image: App Banner Image] <https://www.aidoc.com/book-a-demo/>
>
>
>

--
Sandeep Thakkar

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Robert Haas 2026-02-25 16:30:39 Re: Major Version Upgrade failure due to orphan roles entries in catalog
Previous Message Bruce Momjian 2026-02-25 16:05:39 Re: BUG #19415: Spelling error about 'vacuume' in zh_CN.po