<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Pgbouncer on inetshell</title><link>https://inet.sh/en/tags/pgbouncer/</link><description>Recent content in Pgbouncer on inetshell</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sat, 26 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/en/tags/pgbouncer/index.xml" rel="self" type="application/rss+xml"/><item><title>pgbouncer: 'unsupported startup parameter: extra_float_digits' (and 'no such database')</title><link>https://inet.sh/en/posts/databases/pgbouncer-unsupported-startup-parameter/</link><pubDate>Sat, 26 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/databases/pgbouncer-unsupported-startup-parameter/</guid><description>JDBC, DBeaver, DataGrip, Npgsql or psycopg connect straight to PostgreSQL but through pgbouncer they fail with &amp;#39;unsupported startup parameter: extra_float_digits&amp;#39; (or &amp;#39;options&amp;#39;). pgbouncer rejects session parameters it cannot track across clients; ignore_startup_parameters accepts and drops them. What is safe to ignore, what is not, track_extra_parameters, and the &amp;#39;pooler error: no such database&amp;#39; from the [databases] section.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="c1">; /etc/pgbouncer/pgbouncer.ini</span>
</span></span><span class="line"><span class="cl"><span class="k">[pgbouncer]</span>
</span></span><span class="line"><span class="cl"><span class="na">ignore_startup_parameters</span> <span class="o">=</span> <span class="s">extra_float_digits, options</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">systemctl reload pgbouncer          <span class="c1"># or RELOAD; on the admin console: psql -p 6432 -U pgbouncer pgbouncer</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>extra_float_digits</code> can be ignored with no effect. <code>options</code> (what JDBC and DataGrip use for <code>-c search_path=…</code>) is ignored too, but then the client&rsquo;s <code>search_path</code> <strong>never arrives</strong>: pin it on the role with <code>alter role app set search_path = app, public</code>.</p>
<h2 id="the-error">The error</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">FATAL: unsupported startup parameter: extra_float_digits
</span></span></code></pre></td></tr></table>
</div>
</div><p>or, depending on the client, <code>pooler error: unsupported startup parameter: extra_float_digits</code>. Straight to port 5432 it connects; through pgbouncer&rsquo;s 6432, it does not. JDBC sends it (everything using the PostgreSQL Java driver: DBeaver, DataGrip, Spring, Jenkins), as do Npgsql and some ORMs; other clients send <code>options</code>.</p>
<h2 id="why-it-happens">Why it happens</h2>
<p>When a client opens a connection, it puts the session parameters it wants into the startup packet (<code>extra_float_digits=3</code>, <code>options=-c search_path=app</code>). pgbouncer, in <code>transaction</code> or <code>statement</code> mode, shares one server connection among many clients, so it only lets through the parameters it knows how to store per client and restore on the server when that client&rsquo;s turn comes: <code>client_encoding</code>, <code>datestyle</code>, <code>timezone</code>, <code>standard_conforming_strings</code>, <code>application_name</code>. Anything else would be a setting leaking from one client to another; rather than that, pgbouncer rejects the connection.</p>
<p>Two ways to resolve it:</p>
<table>
  <thead>
      <tr>
          <th>Option</th>
          <th>What it does</th>
          <th>For which parameters</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>ignore_startup_parameters</code></td>
          <td>Accepts the parameter and drops it</td>
          <td>Those that change nothing (<code>extra_float_digits</code>) or that you can pin elsewhere (<code>options</code>)</td>
      </tr>
      <tr>
          <td><code>track_extra_parameters</code></td>
          <td>Stores it per client and restores it on the server, as it does with <code>timezone</code></td>
          <td>Parameters the server reports to the client (<code>ParameterStatus</code>) and that you truly need per session</td>
      </tr>
  </tbody>
</table>
<p><code>extra_float_digits</code> is harmless since PostgreSQL 12: <code>float</code> output is already the shortest exact representation and the parameter changes nothing. <code>options</code> with <code>search_path</code> <strong>does</strong> matter: ignored, the client sees the database&rsquo;s default <code>search_path</code> and unqualified queries fail with <code>relation does not exist</code>. The clean fix is the role:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="cl"><span class="k">alter</span><span class="w"> </span><span class="k">role</span><span class="w"> </span><span class="n">app</span><span class="w"> </span><span class="k">set</span><span class="w"> </span><span class="n">search_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">app</span><span class="p">,</span><span class="w"> </span><span class="k">public</span><span class="p">;</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="no-such-database">&rsquo;no such database'</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">pooler error: no such database: app_db
</span></span></code></pre></td></tr></table>
</div>
</div><p>pgbouncer only routes databases listed under <code>[databases]</code>. Either add the entry, or a wildcard:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="k">[databases]</span>
</span></span><span class="line"><span class="cl"><span class="na">app_db</span> <span class="o">=</span> <span class="s">host=db.example port=5432 dbname=app_db</span>
</span></span><span class="line"><span class="cl"><span class="na">*</span> <span class="o">=</span> <span class="s">host=db.example port=5432</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>With <code>*</code>, a client asking for <code>other_db</code> gets <code>host=db.example dbname=other_db</code>; those automatic entries clean themselves up after <code>autodb_idle_timeout</code>. And check the entry&rsquo;s <code>dbname=</code>: pointing <code>app_db</code> at another database through a copy-paste is common.</p>
<h2 id="traps">Traps</h2>
<ul>
<li><strong><code>RELOAD</code> is enough</strong> for <code>ignore_startup_parameters</code> and <code>[databases]</code>; <code>listen_*</code> and <code>auth_type</code> need a restart.</li>
<li><strong><code>transaction</code> mode and <code>SET</code></strong>: a manual <code>SET search_path</code> in the session is lost as soon as the server connection moves to another client; use <code>SET LOCAL</code> inside the transaction or the <code>alter role</code>.</li>
<li><strong>Named prepared statements</strong> (JDBC <code>prepareThreshold</code>, <code>PREPARE</code>) do not work in <code>transaction</code> mode on old pgbouncer; since 1.21, <code>max_prepared_statements = 200</code> supports them.</li>
<li><strong>SCRAM</strong>: with <code>auth_type = scram-sha-256</code> the <code>userlist.txt</code> needs the SCRAM hash exactly as it comes out of <code>pg_authid</code>, or <code>auth_query</code> so pgbouncer looks it up.</li>
<li><code>SHOW CONFIG;</code> and <code>SHOW DATABASES;</code> on the admin console tell you what is really loaded, not what you think you wrote.</li>
</ul>
<p>See also: <a href="/en/posts/databases/postgresql-admin-cheat-sheet/">PostgreSQL: admin cheat sheet</a>. Reference: <a href="https://www.pgbouncer.org/config.html">pgbouncer.ini</a>.</p>
]]></content:encoded></item></channel></rss>