Skip to main content

App launch returns 502 behind a reverse proxy

If Informer works normally but opening an App returns 502 Bad Gateway, check the reverse proxy's error log. For nginx, this message identifies an upstream response-header limit:

upstream sent too big header while reading response header from upstream

The affected request is usually GET /api/apps/{id}/view/. The ID can be a UUID or an app's natural ID, such as admin:top-customers-by-revenue.

Why it happens​

Before 2026.1.4, in the default Approved resources only mode, the App's Content Security Policy (CSP) response header includes every enabled approved library URL. The policy, authentication cookie, and other headers must all fit within the proxy's upstream header buffer. A default 28-resource tenant was measured at approximately 4.3 KB for the complete response-header block. The actual size varies with the catalog, hostname, URL prefixes, and authentication data.

nginx's proxy_buffer_size defaults to one memory page: 4 KB or 8 KB, depending on the platform. A 4 KB default cannot accommodate that measured response. Increasing request-header limits does not address this response-header error. See nginx's proxy module documentation.

Buffer configuration​

Before 2026.1.4, an 8 KB buffer accommodates the measured default response; 16 KB provides additional headroom. Measure the failing response if errors persist, since neither value guarantees capacity for every installation.

For a directly managed nginx proxy, an example compatible buffer configuration is:

proxy_buffer_size 16k;
proxy_buffers 4 16k;
proxy_busy_buffers_size 32k;

Keep these settings consistent with any existing buffer overrides. The proxy_buffer_size directive controls how much space is available for the upstream response headers.

F5 / NGINX Inc Kubernetes Ingress Controller​

On the Informer Ingress:

metadata:
annotations:
nginx.org/proxy-buffer-size: "16k"
nginx.org/proxy-buffers: "4 16k"
nginx.org/proxy-busy-buffers-size: "32k"

The controller ConfigMap uses proxy-buffer-size, proxy-buffers, and proxy-busy-buffers-size with the same values. Ingress annotations override those defaults. See NGINX Ingress Controller annotations.

Kubernetes ingress-nginx​

This controller uses different annotation names and separates the number of buffers:

metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
nginx.ingress.kubernetes.io/proxy-busy-buffers-size: "32k"

Its ConfigMap keys are proxy-buffer-size, proxy-buffers-number, and proxy-busy-buffers-size. See the controller's annotations and ConfigMap reference.

Measure the failing App response​

Run this command from a shell inside an Informer application pod with curl available. It contacts Informer directly, allowing the headers to be measured before the ingress handles them:

curl -sS -o /dev/null -H 'Host: <public-informer-hostname>' -H 'X-Forwarded-Proto: https' -w 'HTTP status: %{http_code}\nHeader bytes: %{size_header}\n' 'http://127.0.0.1:<informer-http-port>/api/apps/<app-id>/view/?session=<session-jwt>'

Replace the placeholders, including the angle brackets:

  • public-informer-hostname: the hostname in the public Informer URL, without its scheme or path.
  • informer-http-port: Informer's internal HTTP listening port.
  • app-id: the UUID or natural ID from the app-view request. A natural ID may be URL-encoded, such as admin%3Atop-customers-by-revenue.
  • session-jwt: the session parameter of the failing app-view request, which Informer GO adds when it opens an App. It signs in as your account, so keep it private. For an App opened from the web client, which has no session parameter, remove ?session=<session-jwt> and add -H 'Cookie: <cookie>' with the Cookie header of that request instead.

Use the deployment's actual API prefix if it differs from /api. For an HTTP public deployment, use http in X-Forwarded-Proto. If the public URL has a path prefix, add -H 'X-Forwarded-Path: <prefix>', because the policy includes it. The command assumes Informer exposes HTTP inside the pod.

Confirm HTTP 200 before interpreting the byte count; a login redirect or error is a different response. Compare the result with the configured buffer in bytes (16 KB is 16,384 bytes). Record the application pod name and the timestamp of a fresh ingress error. Share the status and count with Support, not the credential.

If the measured response fits, inspect the configuration and reload status of the proxy reporting the new error. nginx -T shows the generated configuration on disk; successful reload logs establish that nginx accepted it. Check the matching hostname and location, including inherited settings.

Behavior in 2026.1.4 and later​

Starting with 2026.1.4, in Approved resources only mode, the App's Content Security Policy names only the approved libraries the App references in its page or its own files, instead of every enabled entry in the catalog. Approved libraries keep their path-level restriction and integrity checks. An App that loads three libraries measured about 1.9 KB for the complete response-header block, and adding libraries the App doesn't reference no longer changes it. Any enabled CDN mode allows libraries by origin, which keeps its header small, so it still allows the whole catalog.

What this means in practice:

  • Most Apps need no changes. The policy is built when the App loads, so it applies to every App right after the upgrade. The exception is an App that assembles a library URL at runtime, described below.
  • Each library the App references adds roughly 55 to 250 bytes, depending on how many files it has. An App that references every library in the default catalog produces about the same 4.3 KB block as before, so heavy library use can still need a larger buffer.
  • Libraries loaded from script are included. Informer also scans the App's JavaScript, TypeScript, CSS, HTML, JSON, Vue, and Svelte files for approved library URLs, so a library the App inserts at runtime or loads with a dynamic import() is allowed as long as its URL appears in those files. A different query string, such as another Google Fonts weight, still matches, and an approved folder or origin (a URL ending in /) covers any URL beneath it. The scan skips server-side folders, Markdown and text files, and files over 2 MB. A URL assembled from pieces at runtime can't be found; spell the full URL in the source instead.

Cookies, embedding allowlists, and headers added by other infrastructure can still affect the required proxy buffer size. Confirm the installed release is 2026.1.4 or later before relying on the changed behavior.