Skip to content

aggregator(config): PM_AGG_PORT / PM_AGG_HOSTS are never validated — port 0 silently binds a random port, a typo crashes with a Bun RangeError that names neither variable, and an all-separator PM_AGG_HOSTS exits 0 serving nothing #2161

Closed

Description

@dezren39

Problem

loadConfig (pm-stack/aggregator/src/config.ts:64-69) performs no validation on the aggregator's bind configuration:

  • port: Number(s(env.PM_AGG_PORT, "4870")) — a bare Number() with no integer/range check.
  • hosts is split/trimmed/filtered with no non-empty check.

server.ts:807-817 then maps one Bun.serve per host and logs whatever port Bun reports.

Evidence (verified this run, main b2b885b9)

Probe 1 — loadConfig itself (bun, importing the real src/config.ts):

  • {PM_AGG_PORT:"0"} → port 0
  • {PM_AGG_PORT:"abc"} → port NaN
  • {PM_AGG_PORT:"4870.5"} → port 4870.5
  • {PM_AGG_HOSTS:","} → hosts []
  • {PM_AGG_HOSTS:" , "} → hosts []

Probe 2 — what Bun does with those ports (sandbox bun 1.4.4, Bun.serve on 127.0.0.1):

  • NaN, 99999, -1, 4870.5 → RangeError [ERR_OUT_OF_RANGE]: The value of "options.port" is out of range… — the process dies at startup with an error that names neither PM_AGG_PORT nor the accepted range, so an operator typo presents as a Bun internals crash.
  • 0 → binds a random ephemeral port (probe got 36279) and server.ts happily logs aggregator listening on http://127.0.0.1:36279. Every consumer of the aggregator expects 4870, so the service is "up" in systemd terms and unreachable in practice — a silent misconfiguration, worse than a crash.
  • hosts [] → servers is an empty array, nothing is bound, nothing is logged, and the process exits 0 immediately — the unit looks like it ran fine while no dashboard exists.

Why it matters

The aggregator is the PM stack's single dashboard URL. Its only two bind knobs can each turn a one-character env typo into either a misleading crash or a silently absent/wrong-port service, and none of the failure modes name the offending variable. Sibling services in this repo already learned this lesson the hard way (the proxy fleet's strict parseProxyPort in bin/proxy-port.mjs exists for exactly this class).

Acceptance criteria

  • loadConfig rejects a PM_AGG_PORT that is not an integer in 1–65535 (0 included — an ephemeral aggregator port is never useful) with an error naming PM_AGG_PORT, the received value, and the accepted range; the process fails at startup, before binding.
  • loadConfig rejects a PM_AGG_HOSTS that yields zero bind addresses with an error naming PM_AGG_HOSTS.
  • Valid configurations are unchanged: unset → port 4870, hosts ["127.0.0.1"]; explicit valid port/hosts pass through.
  • Tests for loadConfig cover: "abc", "0", "-1", "99999", "4870.5" rejected; "," / " , " hosts rejected; defaults accepted.

Triage should pin whether validation lives in loadConfig (throwing) or in server.ts before serving, and whether port 0 deserves a deliberate opt-in instead of a rejection.

Activity

  1. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    effort/xsTrivial: expected under 30 minutes of work
    on Oct 29, 2026
  3. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator job (new-issue-creator-code-b)
    • Session / ID: cron new-issue-creator-code-b, run 2026-10-29 01:50 CDT
    • Found via: filed this run
    • Task: Triage the unvalidated aggregator bind config (pm-stack/aggregator/src/config.ts:64-69): pin where validation lives and whether port 0 is rejected or an explicit opt-in, then route a small_fix packet.
    • Expectation: effort/xs; done = PM_AGG_PORT non-integer/out-of-range/0 fails at startup naming the variable, all-separator PM_AGG_HOSTS fails naming the variable, defaults unchanged, loadConfig tests added.
    • Links: evidence file hidden_files/issue-code-aggconfig-body.md (bun probes of the real loadConfig + Bun.serve, main b2b885b)
  4. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — design-architect pass 22 (2026-10-30): ADOPTED as Phase 2 of design #2835 (pm-stack services, with #2758/#2172): this issue lands via a per-app config helper in the aggregator's config.ts carrying the design's contract (digits-only, port 1-65535 with 0 invalid, hosts list non-empty after filter, boot failure naming the variable) plus the shared probe matrix as tests — not a one-off patch. Linked as a sub-issue of #2835 (verified in its sub_issues list). Triage: do NOT re-file/re-scope/split this issue; record the phase structure and land it as the phase, with the decisions recorded on #2835 and in its design doc (files/designs/code-env-config-strict-parse.md). This issue keeps its own queued triage packet.

  5. 19 remaining items

  6. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — done — OpenChamber scheduled lane

  7. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · triage verdict — already done, closing

    • Agent: repo-worker-code (lane code-k)
    • Session / ID: queue task 7840
    • Found via: repo-health-code-pilot atomic claim
    • Task: Triage aggregator(config): PM_AGG_PORT / PM_AGG_HOSTS are never validated — port 0 silently binds a random port, a typo crashes with a Bun RangeError that names neither variable, and an all-separator PM_AGG_HOSTS exits 0 serving nothing #2161 (aggregator PM_AGG_PORT / PM_AGG_HOSTS never validated).
    • Verdict: ALREADY FIXED upstream — every acceptance criterion is met at current main (443e1d91b). The fix landed as commit 378c4d971 "fix(aggregator): validate bind configuration" (2026-11-01), merged via PR fix(design-code): repoint :18745 legs to antigravity-direct :18751 (#1413, unblocks opencode#1409) #4626, after this issue's evidence was gathered at b2b885b9:
      • pm-stack/aggregator/src/config.ts parseAggregatorPort: unset/blank → 4870; otherwise the value must match /^\d+$/ and be a safe integer in 1–65535, else it throws Invalid PM_AGG_PORT=<value>; expected a decimal integer in range 1-65535 — naming the variable, the received value, and the range, at loadConfig time (startup, before any bind). Port 0 is rejected; there is no opt-in — that pins the triage question the issue left open.
      • parseAggregatorHosts: unset/blank → ["127.0.0.1"]; a value yielding zero hosts (,, ,) throws Invalid PM_AGG_HOSTS=<value>; expected at least one non-empty host.
      • Tests: pm-stack/aggregator/test/config.test.ts (added by the same commit) covers defaults, valid pass-through, and rejection of "0", "abc", "12.5", "-1", "99999", "0x10", "1e3", "4870oops" and of "," / " , , " hosts.
      • Independently re-run this triage on the laptop at current main: bun test test/config.test.ts — 6 pass, 0 fail.
    • State: closing as completed. Task 7840 completes as already_done; claim labels removed by this lane.
  9. added
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 3, 2026
  10. developing-today commented on Nov 3, 2026

    @developing-today
    Contributor

    agent-note:v1
    state: triaged (coverage pass)
    Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
    Found via: coverage pass 2026-11-03

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/xsTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)queue/queuedHas a queued task in the Supabase agent queuesource/creatorFiled by the new-issue-creator jobsource/design-architectFiled by the repo design architect jobstatus/needs-triageNot yet triaged; needs a first looktask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions