Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vtLlP-000lCx-20 for pgsql-bugs@arkaria.postgresql.org; Fri, 20 Feb 2026 08:21:27 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vtLlO-006x6F-1d for pgsql-bugs@arkaria.postgresql.org; Fri, 20 Feb 2026 08:21:26 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vshRN-00FyoN-0a for pgsql-bugs@lists.postgresql.org; Wed, 18 Feb 2026 13:18:05 +0000 Received: from mail-qt1-x834.google.com ([2607:f8b0:4864:20::834]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vshRK-00000001DeJ-0De8 for pgsql-bugs@lists.postgresql.org; Wed, 18 Feb 2026 13:18:04 +0000 Received: by mail-qt1-x834.google.com with SMTP id d75a77b69052e-506e287dd53so11128851cf.1 for ; Wed, 18 Feb 2026 05:18:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1771420682; cv=none; d=google.com; s=arc-20240605; b=MkLJ/mSGBSOfUJedrHvBaKubMcQf2Luq3SVJ7LQo+dP7b2bD5F2Ggg8d3sZ+Idh5n7 0XnnIkC8MoQXmGD7Vh3jARzJwEEBOGapV109fsA3gl7VpgC2XogOjFhRwaNin57ZRcdL /IID94GjQHWJgfuCuKMr6603XL4jjDZNNWqS4aF6BYuxR9rk+QAH5Xi1ld57NDVdTXPA Pd5DKjt9V9r+vAxgrEA3+/mzW0bYNZo2rs2YVfJnzSLC9dc/yDVKn9VFe3GcZDxVj1dw 71xzqkCemyp/O4rnNkOBtNMpx9ksm65TwFbv8JF4Z49n/hkhHoktZgJAu7ThdvIJ79ZJ cyjw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:mime-version:dkim-signature; bh=Yu7tMsiLhO44KsZ6NqxsaiMPUx2ospqeiYJoKe3Gek8=; fh=wCeXnVuaXNtkO880pEEYVyLt4mrAEK1VEfi14BMBHFs=; b=g7MBRLYPVQDkQYhW9cbzUYNTI8tBwYI1KE8XOGs15WVV1cNSftSg8RNgQ20cLMUzCz KDzlj42lbrBCD9RHtpzKY+1jt0Tia+T9CQFB1tDw6q0J/9PKwxV/opOG5hDzUxhw4lsh rl2nav/bVg8ABrpbkLON4GZCH0qQW4t79gccuJQsIW+ENBe4WYOXsFamyJwvTeATlCw3 t6/F6TtoOqgDrJLCTIM4TLkuJC7anEGuxMVwK+MfbSG+h9ehhMaX0Ij7i5xcbFTGdoE7 0BQ/AogNIFkZI6AHPLWB33gkMuHKWPDqluPxKfHdicrYCCodvmoJbsAoJAp9VKgTci2S sa1Q==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aidoc.com; s=google; t=1771420682; x=1772025482; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=Yu7tMsiLhO44KsZ6NqxsaiMPUx2ospqeiYJoKe3Gek8=; b=m2KZjEHMm+YTo8fRRAcW4a031LFbgsJ8RZEzWzwNQvR/HU7avzLoHvSjjF8eeA97p1 f9/U5imVJy/3bm5IMGIL3qlVHg6fA+o+m29EARH4H4lO9yRK7TPY2j+RcAH0ZtzVb5C6 khsiizUOD2hTmY5WMjG5NBhifG1JejteAyKn8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771420682; x=1772025482; h=cc:to:subject:message-id:date:from:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Yu7tMsiLhO44KsZ6NqxsaiMPUx2ospqeiYJoKe3Gek8=; b=U8Ro/JCFOsaKO5Bh2abXAbNG0A8xSk9GbJKcC5oYGHEjDU/wU/BUYCHLv8wOJyag1e lq02NRX88I7wPx3mAT3y2edOX/w5BWai3wesToMicLWd6kMSD+UGcXZ8bg/JeHLl5nOo 57K1FKbGXywJPZhuVEktZrPg8LqcSWCUyuA5ddffYefGFZmLBSQOlZv9L5UwK6s1A4Vw LQpZX8f3uC8PxW/UCWmxz0HiODY3BPyfBPgB1MjaT832/sYROvWQYptltlIiXzWtJiFJ DgyeWmcTWEZlw3FilDTlhCP2zqVo6m/HgExyPn6G5YEATBMfpjbKl7JUK6rKGzTtxyhR RnBQ== X-Gm-Message-State: AOJu0YxKXZNEFqTu2d+qbcGKUibEiO8MSpXwl+58VQz5HpOaTkY9d+Zq /jihtjnOgSkHIUg0ilck0MzqisgU4B/YnF+UOwhpy2htIKCL78F8KVJU6YQTusxNltT1aPkM9jr Z1Nlwc7tOWllkj9Vykt4b1ja3R4WpK1IVgB5yzvJg4maCy1gQ3pYnFM8= X-Gm-Gg: AZuq6aL2MsjJnt4uecv36Vw1kU1tPsLb7qEJlqhC2NsVjL8WwAE1IEsG2Xkqr16ADGM 2WsFrPBHukUb6+i262TD/u2Gp+qDZuyvTx7mPI8dcXrgXjrjV6yi3ftKS7sp8/jWQ6poxn2ICFH EZK1NPeYMS8I9wHFyoz6zS8XfrN91IuSiSJKy45vcraRJl1/qqtXnWFMpJQ9/r1KXOGOlfdeINk m7EP7JamgnBH4lpsD8BB+rJLUKoRv68We/u7XIhQbHQj5SD4VQ8IRaJFFnnYY7zDpBL5YXZuLn5 7BMJmG0= X-Received: by 2002:a05:622a:189a:b0:501:3b29:dc25 with SMTP id d75a77b69052e-506a6b34368mr217309781cf.60.1771420681359; Wed, 18 Feb 2026 05:18:01 -0800 (PST) MIME-Version: 1.0 From: Ben Caspi Date: Wed, 18 Feb 2026 15:17:50 +0200 X-Gm-Features: AaiRm50pwTKOesroHZZdv6-MXQpkeH4f48nvtmdoxxPtVJeEtCAGSVksIWo56P0 Message-ID: Subject: PostgreSQL MSI ignores --datadir flag during minor upgrade on Windows To: pgsql-bugs@lists.postgresql.org Cc: Avi Uziel , Liran Amrani , Shahar Amram Content-Type: multipart/alternative; boundary="00000000000075e803064b1904a6" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --00000000000075e803064b1904a6 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable 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`" --loca= le > `"$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. In server/pgserver.xml.in, in the server component=E2=80=99s preInstallationActionList: *pgserver.xml.in * Lines 1142-1153 > > datadir > ${iDataDirectory} > > > ${iDataDirectory} > not_empty > > > > *iDataDirectory is read from the registry here:* *pgserver.xml.in * Lines 1003-1008 > > Data Directory > > HKEY_LOCAL_MACHINE\SOFTWARE\PostgreSQL\Installat= ions\postgresql${service_suffix}-${product_version} > iDataDirectory > *What goes wrong:* When passing --datadir "F:\AidocData\PostgreSQL\15\data" on the command line, the wizard sets datadir =3D "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. - 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: > > datadir > ${iDataDirectory} > > > ${iDataDirectory} > not_empty > > > ${datadir} > empty > > > > This keeps the current behavior when --datadir is not passed, but ensures that an explicit --datadir is not overridden by the registry. Please consider investigating this issue and its solution. If I misunderstood anything please let me know. Thanks! --=20 [image: photo] Ben Caspi DevOps Engineer www.aidoc.com | benc@aidoc.com [image: linkedin] [image: twitter] [image: App Banner Image] --00000000000075e803064b1904a6 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hello,

Rece= ntly 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 u= pgrade (15.13 --> 15.16) we've noticed that post-upgrade the Postgre= SQL service assigned=C2=A0data directory changed to the default value "= ;C:\Program Files\PostgreSQL\15\data".

Our cl= ient's data directory prior to the upgrade was "F:\AidocData\Postg= reSQL\15\data". This change caused data to be written to the=C2=A0wron= g location until we found the issue.

This is the c= ommand we use for the upgrade:
Start-Process $installer_e= xe -ArgumentList "--unattendedmodeui minimal --mode unattended --super= account $POSTGRES_ROOT_USER --superpassword $POSTGRES_ROOT_USER_PWD --serve= rport $port --datadir `"$data_dir`" --locale `"$locale_name`= "" -Wait

I looked into your cod= ebase and found that during an upgrade the installer defaults to the Regist= ry value for data directory and ignores the --datadir flag I provided in my= command.

In server/pgserver= .xml.in, in the server component=E2=80=99s preInstallationActionList:
pgserver.xml.in
Lines 1142-1153
<= br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<= !-- Set datadir if an existing installation is found -->
=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0<setInstallerVariable>
=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<name>datadir</nam= e>
= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<= ;value>${iDataDirectory}</value>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<ruleList>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<strin= gTest>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<text>${iDataDirec= tory}</text>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<type>not= _empty</type>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0</stringTest>
=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<= ;isFalse value=3D"${extract_mode}"/>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0</ruleList>
=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0</setInstallerVariable>

iDataDirectory is read from the registry here:
pgserver.xml.in
Lines 1003-1008

= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<!-- Get the= existing data directory. -->
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<registryGet><= br aria-hidden=3D"true">=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<name>Data Directory</name>
=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<key>HKEY_LOCAL_MACHINE\SOFTWA= RE\PostgreSQL\Installations\postgresql${service_suffix}-${product_version}&= lt;/key>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<variable>iDataDir= ectory</variable>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0</registryGet>
What goes wrong:
When passing --data= dir "F:\AidocData\PostgreSQL\15\data" on the command line, the wi= zard sets datadir =3D "F:\AidocData\PostgreSQL\15\data".

Later, in preInstallationActionList, the installer read= s iDataDirectory from the registry.
If iDataDirecto= ry is not empty, it overwrites datadir with that value.
  1. = There is no check that the user explicitly provided --datadir, so the CLI v= alue is ignored.
If the registry still has the old default path (e.g. C:\Progra= m Files\PostgreSQL\15\data), the service ends up re-registered with that pa= th instead of F:\AidocData\PostgreSQL\15\data.
When= the registry can be wrong
  • Initial install used the defa= ult data directory, then data was moved to=C2=A0F:\AidocData\PostgreSQL\15\= data=C2=A0and the service was updated manually, but the PostgreSQL registry= key was not.
  • 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 tha= t datadir is set from iDataDirectory only when datadir is empty:

<!-- Set datadir = if an existing installation is found (only when user didn't provide --d= atadir) -->
<setInstallerVariable>
=C2=A0=C2=A0=C2=A0=C2=A0<name>datadir= </name>
=C2=A0=C2=A0=C2=A0=C2=A0<value>${iDataDirectory}</value>= ;
=C2= =A0=C2=A0=C2=A0=C2=A0<ruleList>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0<stringTest>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0<text>${iDataDirectory}</text>
=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<type>not_empty= </type>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0</stringTest>=
=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<stringTest>
=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<text>${data= dir}</text>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0<type>empty</type>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0</stringTest>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<= isFalse value=3D"${extract_mode}"/>
=C2=A0=C2=A0=C2=A0=C2=A0</rul= eList>
</setInstallerVariable>

This keeps the cur= rent behavior when --datadir is not passed, but ensures that an explicit --= datadir is not overridden by the registry.

Please consi= der investigating this issue and its solution.
If I misunderstood= anything please let me know. Thanks!
--
--00000000000075e803064b1904a6--

3D"photo"

Ben Caspi
DevOps Engineer

3D"twitter"

= www.aidoc.com=C2=A0=C2=A0|=C2=A0=C2=A0

3D"linkedin"


3D"App


=C2=A0