Re: PostgreSQL MSI ignores --datadir flag during minor upgrade on Windows - Mailing list pgsql-bugs
| From | Sandeep Thakkar |
|---|---|
| Subject | Re: PostgreSQL MSI ignores --datadir flag during minor upgrade on Windows |
| Date | |
| Msg-id | CANFyU95x5LbDf-4neKNqOgQmO42Kqe+cj8kuAafh-DipsZc9eg@mail.gmail.com Whole thread |
| In response to | PostgreSQL MSI ignores --datadir flag during minor upgrade on Windows (Ben Caspi <benc@aidoc.com>) |
| List | pgsql-bugs |
On Fri, Feb 20, 2026 at 1:51 PM Ben Caspi <benc@aidoc.com> wrote:
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.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`"" -WaitI 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.
In server/pgserver.xml.in, in the server component’s preInstallationActionList:
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
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.
- 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.
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!
Sandeep Thakkar
pgsql-bugs by date:

