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 1wVANd-001kIP-0q for pgsql-bugs@arkaria.postgresql.org; Thu, 04 Jun 2026 15:53:13 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wVANc-007bp7-0g for pgsql-bugs@arkaria.postgresql.org; Thu, 04 Jun 2026 15:53:12 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wUtyT-003k0C-0T for pgsql-bugs@lists.postgresql.org; Wed, 03 Jun 2026 22:22:09 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wUtyQ-0000000182h-2zIq for pgsql-bugs@lists.postgresql.org; Wed, 03 Jun 2026 22:22:08 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=kuU1hF92oQ87EmDcIziMeW/5lSWSuo/8ruJB4IUt3ig=; b=36zBBhpPFUNgAXd8m/3im53/wb 2aRBtH6zcHi5D/Yvhnc4S2y4p3iuWDI2yX0klBVZwMdTER3bCoxMtJTG3ivYf1o2e0D/pbOSRYbFU sdWlnEQNJj7oY9B7oTyNvBgFmWawUnL/mguzb8j6qW6It+wUCdQMVmpi/RTvwtnTgqLxZ9rR6y30F uWdxQT/nN6M4YEUpdI5ZDDw1v5I9yKd1KwLnmv2itQ/daZuIbdvh8DmWQfTl7JwmnRIS8WS3vAuYt 9v3oljEoD2WsaeNzfzDHdM1bDLcQgw7obokag7UNMqKJxDfKHFwVPEldsEaMP9/FyG7nPfi0RnjRV jEeTE3KA==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wUtyP-002zLh-0u for pgsql-bugs@lists.postgresql.org; Wed, 03 Jun 2026 22:22:05 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wUtyN-006jPu-2J for pgsql-bugs@lists.postgresql.org; Wed, 03 Jun 2026 22:22:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19506: LOAD '$libdir/...' inside extension scripts ignores dynamic_library_path with extension_control_path To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: gabriele.bartolini@gmail.com Reply-To: gabriele.bartolini@gmail.com, pgsql-bugs@lists.postgresql.org Date: Wed, 03 Jun 2026 22:21:28 +0000 Message-ID: <19506-9478f3012ecc2328@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19506 Logged by: Gabriele Bartolini Email address: gabriele.bartolini@gmail.com PostgreSQL version: 18.4 Operating system: Linux (reproduced under CloudNativePG/Kubernetes) Description: =20 When an extension is installed in a location reached via `extension_control_path` / `dynamic_library_path` (rather than the compiled-in package library directory), a LOAD '$libdir/foo' hardcoded inside an extension's SQL script fails to find the library. PostGIS does this in its upgrade scripts, so a PostGIS upgrade fails: ``` app=3D# SELECT postgis_extensions_upgrade(); NOTICE: Updating extension postgis 3.6.1 ERROR: could not access file "$libdir/postgis-3": No such file or directory CONTEXT: SQL statement "LOAD '$libdir/postgis-3'" extension script file "postgis--ANY--3.6.3.sql", near line 1530 ``` This is a side effect of the fix for bug #18920 (commit f777d773878). Commit 4f7f7b03758 (`extension_control_path`) made the feature work by stripping the '$libdir/' prefix so that dynamic_library_path is consulted. #18920 then restricted that stripping to the function-load path so that a user-issued `LOAD` keeps the literal '$libdir/' prefix. As a result, a `LOAD` inside an extension script now also keeps the literal prefix, so `dynamic_library_path` is never consulted, and the library cannot be found. A `LOAD` running inside an extension script should behave like the extension's function loads (strip '$libdir/'), while a LOAD issued directly by a user should keep it (the #18920 behaviour). The two can be distinguished by `creating_extension`. Reproduced with the CloudNativePG operator on Kubernetes, but it applies to any setup using `extension_control_path` / `dynamic_library_path`.