# Reported issues for Helio

Pod holds 19 of 35 GitHub reports that passed its relevance review. This can include external user reports, maintainer-confirmed bugs, and concrete feature gaps. Treat them as evidence to inspect, not a count of distinct defects.

Back to [Helio](/mcp/helio).

## Most discussed

### [Feature] Dashboard: session_source filter and Session / Agent column rework

## Problem

Audit records carry `session_source` since #218 (which identity strategy produced the session id: `header`, `meta`, `legacy_header`, `transport`, or `sideband`), and the audit detail panel shows it. But there is no way to filter the Feed or Audit views by it, and the `Session / Agent` column still renders `agent_id ?? session_id` with no hint of provenance. An operator watching a legacy_header deprecation migration cannot answer "which callers still resolve through the legacy…

[Read the thread](https://github.com/gethelio/helio/issues/250) · 2026-08-06 · closed · outside contributor · 4 comments

### [Bug] Config watcher silently stops observing a config replaced by an unreadable file

## Description

When the config file a running proxy watches is replaced by a file the proxy user cannot read, the proxy can lose its watch without logging anything: no `Policy reloaded`, no `Config reload failed` line, nothing. It keeps serving the last policy it read, and it observes no later edit to the file, in place or rename-style, even after the file's ownership is repaired, until it is restarted. The trigger is the natural edit mistake on a separate-user install: the proxy runs as…

[Read the thread](https://github.com/gethelio/helio/issues/352) · 2026-09-03 · closed · outside contributor · 2 comments

### [Feature] Config integrity: audited policy reload events and optional hash pin

## Problem

Hot reload is on by default (`policies.hot_reload` is treated as `true` when unset). `ConfigWatcher` fires on change, waits 50ms for the write to settle plus a 200ms debounce, recompiles, and swaps the rule set atomically via `governedForwarder.updatePolicy()` on every governed stack and `governanceService.updatePolicy()` on the sideband. Measured end to end on 2026-09-02: a deny rule became allow 0.4 to 0.5 seconds after an in-place write, on a local process and inside the…

[Read the thread](https://github.com/gethelio/helio/issues/341) · 2026-09-02 · closed · outside contributor · 2 comments

### [Bug] HTTP upstream forwarders let McpRequest.headers override the content-type of the body they serialize

## Description

Both HTTP upstream forwarders serialize the outbound JSON-RPC body themselves and seed the header merge with a truthful `content-type: application/json` base (`packages/proxy/src/upstream/streamable-http-forwarder.ts` around line 322, `packages/proxy/src/upstream/sse-forwarder.ts` around line 129). `mergeUpstreamHeaders` applies caller-forwarded headers over that base (`merge-headers.ts`, precedence base -> forwarded -> static), so a caller-supplied `content-type` in…

[Read the thread](https://github.com/gethelio/helio/issues/287) · 2026-08-15 · closed · outside contributor · 2 comments

### [Bug] GET /sse mints unbounded sessions from any origin, with no Origin header to gate on

## Description

`GET /sse` mints a session on every request with no cap and no caller identification, so any
web page can create unbounded sessions on a loopback Helio.

`packages/proxy/src/transport/sse.ts:79-105` allocates a `randomUUID()` session and a
`TransformStream` writer per `GET`, storing both in the module-level `sessions` map. Nothing
bounds the map's size. The stale sweeper only evicts after `STALE_THRESHOLD_MS` (90s), so a
page issuing requests in a loop accumulates sessions far…

[Read the thread](https://github.com/gethelio/helio/issues/232) · 2026-08-03 · closed · outside contributor · 2 comments

### [Bug] helio start reports config compile errors as unhandled promise rejections

## Description

`helio start` reports config compile errors as unhandled promise rejections with a stack trace, instead of the clean one-line error every other CLI surface prints.

`startCommand` wraps `loadConfig` in a try/catch that handles `ConfigError` (`cli.ts:317-327`), but nothing wraps the compile step that follows. A config whose YAML is schema-valid yet fails to compile — a catastrophic or malformed regex in `match.input`, or in a budget contributor's `match.input` — throws…

[Read the thread](https://github.com/gethelio/helio/issues/195) · 2026-07-24 · closed · outside contributor · 2 comments

### [Bug] Published Docker image ghcr.io/gethelio/helio is private (anonymous pull returns 403)

## Description

The published container image `ghcr.io/gethelio/helio` is not publicly pullable.
An anonymous pull returns 403, and the ghcr token endpoint refuses to issue an
anonymous pull token, which means the package is private.

Helio is open source, and the CHANGELOG states the Docker image
(`ghcr.io/gethelio/helio`) "is released together" with the proxy and SDK under
each version, so the image is expected to be publicly pullable.

Verified the detection method against a known-public…

[Read the thread](https://github.com/gethelio/helio/issues/99) · 2026-07-01 · closed · outside contributor · 2 comments

### [Bug] helio start crashes with an uncaught EADDRINUSE after printing its listening line when a configured port is in use

## Description

`helio start` attaches no `error` handler to any of its three `serve()` calls (`packages/proxy/src/server.ts:334` and `:353` for the listen and sideband servers, and the dashboard server beside them). `serve()` returns from `server.listen(port, host)` before the bind completes, and the CLI prints `Helio proxy listening on http://<host>:<port>` (`cli.ts:669`) synchronously after the three calls return. When any of the three configured ports (`listen.port`, `dashboard.port`,…

[Read the thread](https://github.com/gethelio/helio/issues/375) · 2026-09-10 · closed · outside contributor · 1 comment

## Most recent

### [Bug] A respawned stdio upstream child is never sent initialize

## Description

When a stdio upstream child exits unexpectedly, the stdio wrapper respawns it and forwards the next request to the new child without sending `initialize` first. Nothing in the transport replays the handshake: `StdioForwarder.forward` writes the request it is given (`packages/proxy/src/transport/stdio-wrapper.ts`), and `onUnexpectedExit` only restarts the process.

A server that enforces the MCP handshake (FastMCP-style servers reject requests before initialization) then rejects…

[Read the thread](https://github.com/gethelio/helio/issues/459) · 2026-09-29 · open · outside contributor · 0 comments

### [Bug] A graceful stop drops pending sideband evaluations without an evaluation_expired record

## Description

A graceful stop drops every pending sideband evaluation without writing a record. `GovernanceService.close()` clears the pending map (`packages/proxy/src/sideband/governance-service.ts:1592`, `this.pending.clear()`) and nothing finalizes the entries first.

An evaluation that is never audited is supposed to end as an `evaluation_expired` audit record, which `docs/adapter-api.md` calls a bypass/tamper signal to surface in monitoring. An evaluation that is still pending when the…

[Read the thread](https://github.com/gethelio/helio/issues/458) · 2026-09-29 · open · outside contributor · 0 comments

### [Bug] Opening the bind-mounted audit database from the Docker Desktop host while the container holds it corrupts it on the next container write

## Description

On Docker Desktop (macOS), when the audit database lives on a host directory bind-mounted into the container, opening that file from the host (`sqlite3`, or `helio export` run on the host) while the proxy container holds it open leaves the container's connection with a stale view of the write-ahead log. The next audit write from the container lands on that stale view, and the container's shutdown checkpoint then writes a main file that is no longer a SQLite database. The next…

[Read the thread](https://github.com/gethelio/helio/issues/359) · 2026-09-07 · closed · outside contributor · 0 comments

### [Docs] The Docker quickstart's single-file config mount misses rename-style saves

## Problem

`docker/docker-compose.yml` bind-mounts the quickstart config as a single file (`./helio.docker.yaml:/config/helio.yaml:ro`). A single-file bind mount binds an inode. An editor that saves by writing a temporary file and renaming it over the original (VS Code, vim, and most editors with atomic saves) gives the file a new inode, and the running container keeps the old one: the edit is not hot-reloaded until the container is recreated, while an in-place save (`printf > file`, `sed -i`…

[Read the thread](https://github.com/gethelio/helio/issues/353) · 2026-09-03 · closed · outside contributor · 0 comments

### [Bug] Config watcher crashes the proxy when the config is replaced by a file it cannot read

## Description

When the config file a running proxy watches is replaced by a file the proxy user cannot read, the watcher's attempt to re-watch the replaced path throws `EACCES`, the rejection is unhandled, and the proxy exits. The trigger is the natural edit mistake on a separate-user install: the proxy runs as `helio` and reads `/etc/helio/helio.yaml` (`root:helio 0640`); an operator copies the file somewhere, edits the copy, and `mv`s it back over the original as root, which leaves the new…

[Read the thread](https://github.com/gethelio/helio/issues/351) · 2026-09-03 · closed · outside contributor · 0 comments

### [Bug] Streamable HTTP forwarder relays a caller-supplied mcp-session-id on the legacy leg

## Description

On the legacy leg, the Streamable HTTP upstream forwarder lets a caller-supplied `mcp-session-id` in `McpRequest.headers` reach the upstream verbatim when no transport session id is in play. `send()` merges `McpRequest.headers` into the outbound headers (`packages/proxy/src/upstream/streamable-http-forwarder.ts` around line 322), assigns `headers['mcp-session-id'] = session.sessionId` only when that id is set (line 333), and deletes the key only on the modern path (line 338). So…

[Read the thread](https://github.com/gethelio/helio/issues/288) · 2026-08-15 · closed · outside contributor · 1 comment

### [Bug] Synthesized results echo a client's id: null back as the response id

## Description

Both of Helio's synthesized results echo the client's request id with a null fallback:
`makeDryRunResult` (`packages/proxy/src/policy/governed-forwarder.ts:1916`) and the #219
dual-era bridge's `synthesizeInitializeResult`
(`packages/proxy/src/upstream/streamable-http-forwarder.ts:160`) both build
`id: request.id ?? null`.

That fallback is reachable. The streamable-http notification fork diverts only
`id === undefined` (`packages/proxy/src/transport/streamable-http.ts:176`); an…

[Read the thread](https://github.com/gethelio/helio/issues/282) · 2026-08-14 · open · outside contributor · 0 comments

### [Bug] Synthesized response bodies echo an explicit id: null, which the 2026-07-28 shape does not permit

## Description

Four sites that synthesize a JSON-RPC response body to a parsed request coerce the request's
own id with `request.id ?? null`:

```
packages/proxy/src/transport/response-normalizer.ts:70        wrapped upstream failures (-32603)
packages/proxy/src/policy/governed-forwarder.ts:1916          dry-run result synthesis
packages/proxy/src/policy/governed-forwarder.ts:2004          policy-denial error bodies
packages/proxy/src/upstream/streamable-http-forwarder.ts:160…

[Read the thread](https://github.com/gethelio/helio/issues/280) · 2026-08-14 · open · outside contributor · 0 comments

### [Bug] Mcp-Name can diverge from the body for a non-idempotent params toJSON

## Description

`buildStandardRequestHeaders` (`packages/proxy/src/upstream/standard-headers.ts`) derives `Mcp-Name` by calling `params.toJSON()` once to peek at the value the body will carry (the module deliberately resolves `toJSON` early — see its own comment). The forwarded body is then produced by a separate `JSON.stringify(body)` in the forwarder, which invokes the same object's `toJSON()` a SECOND time.

For an ordinary (idempotent) `toJSON`, both invocations return the same value and…

[Read the thread](https://github.com/gethelio/helio/issues/267) · 2026-08-09 · open · outside contributor · 1 comment

### [Bug] Mcp-Name under-stamps when the name field is a nested object with its own toJSON

## Description

`buildStandardRequestHeaders` (`packages/proxy/src/upstream/standard-headers.ts`) now derives `Mcp-Name` from the value `JSON.stringify` will actually place on the wire: it resolves a top-level `params.toJSON()` and then reads an own-enumerable string `name`/`uri`. This closed the header-vs-body divergence for a `toJSON` that rewrites, drops, or is inherited/non-enumerable.

One microscopic blind spot remains, surfaced in external review round 2 and left out of that round's…

[Read the thread](https://github.com/gethelio/helio/issues/266) · 2026-08-09 · open · outside contributor · 0 comments

### [Bug] SSE upstream forwarder relays caller-supplied mcp-method and mcp-name headers

## Description

#217 gave the Streamable HTTP upstream forwarder ownership of the `mcp-method`/`mcp-name` wire headers: `send()` deletes any merged residue of either key before stamping body-derived values, and the session manager enforces the same at its merge sites. The deprecated HTTP+SSE upstream forwarder did not get the same treatment. Its POST leg (`packages/proxy/src/upstream/sse-forwarder.ts`, header merge around line 129) merges `McpRequest.headers` into the outbound request without…

[Read the thread](https://github.com/gethelio/helio/issues/264) · 2026-08-09 · closed · outside contributor · 1 comment

The remaining reports are on [the project's issue tracker](https://github.com/gethelio/helio/issues).
