Skip to content

[Bug] v3.4.2: Custom slash commands never appear — deferred-session hydration race leaves slashCommands permanently empty #173

Description

@zaxbysauce

[Bug] v3.4.2: Custom slash commands never appear — deferred-session hydration race leaves slashCommands permanently empty

Problem

After updating to v3.4.2 (Released Jul 22, 2026), custom slash commands defined in ~/.zcode/commands/ or <project>/.zcode/commands/ are no longer registered. The slash command picker shows "No slash commands have been broadcast for the current ZCode Agent session" even though:

  • The command .md file exists and parses correctly
  • Plugin-shipped commands (code-review, commit, feature-dev) are also missing from the picker
  • Skills and agents ARE discovered and shown correctly

This is a regression — the same command files worked in v3.3.6 and earlier. It affects every workspace, every session.

Root Cause

v3.4.2 introduced "non-project conversation mode" which creates sessions with persistence: "deferred" (draft sessions). The renderer populates the slash command list via a one-shot hydration effect that calls the agent backend to fetch configOptions + slashCommands for the newly-created session. But the deferred session is not yet persisted when the hydration query runs (~300ms later), so the agent throws "Session not found" and the .catch() handler silently leaves slashCommands: [] in the renderer store.

The hydration effect never retries. Sending messages, waiting, or restarting the agent process does not trigger re-hydration. The slash command list stays empty until the user manually clicks "Reload Session" in the workspace header.

Reproduction

  1. Install ZCode v3.4.2 on Windows 11.
  2. Create a custom command: ~/.zcode/commands/test-cmd.md with frontmatter:
    ---
    description: A test command
    ---
    Hello from test command
  3. Open any workspace in ZCode.
  4. Type / in the chat input.

Expected

The slash command picker shows /test-cmd (and plugin commands like /code-review, /commit).

Actual

The picker shows "No slash commands have been broadcast for the current ZCode Agent session." Only Skills and Agents sections are populated.

Evidence (agent logs)

From ~/.zcode/cli/log/zcode-2026-07-22.jsonl — two independent workspaces, same failure pattern:

Workspace 1: E:\ZCode\opencode-swarm

13:16:43.295  zcode_protocol.session_create.completed
  sessionId: sess_3119333c-ed36-47d1-b310-14058caca6fa
  persistence: "deferred"
  workspacePath: "E:\ZCode\opencode-swarm"

13:16:43.683  zcode_protocol.v4.gateway_error  (388ms later)
  error: "Session not found: sess_3119333c-ed36-47d1-b310-14058caca6fa"
  scope: "v4.hydrate"

Workspace 2: E:\ZCode

14:34:48.806  zcode_protocol.session_create.started
  sessionId: sess_21fd9777-3c69-42b8-94a9-6da88fe9850a
  persistence: "deferred"
  workspacePath: "E:\ZCode"

14:34:49.081  zcode_protocol.session_create.completed  (275ms)

14:34:49.356  zcode_protocol.v4.gateway_error  (275ms after create)
  error: "Session not found: sess_21fd9777-3c69-42b8-94a9-6da88fe9850a"
  scope: "v4.hydrate"

Both sessions were created with persistence: "deferred". Both failed hydration with "Session not found" in scope: "v4.hydrate" within ~300-400ms of creation.

Plugin resolution confirms command roots exist but are never served to the renderer:

bootstrap.app.startup.plugins.completed:
  commandRootCount: 3
  diagnosticCount: 1
  enabledPluginCount: 10
  pluginStorageRoot: "C:\Users\Brett\.zcode\cli\plugins"

Workaround

Click the "Reload Session" button (circular arrow ⟳ icon in the workspace header). This triggers handleReloadSession, which restarts the workspace agent and re-runs TA() (session preparation). By the time the re-hydration query runs, the session has been promoted from deferred to immediate persistence, so the agent finds it and returns slash commands correctly.

Suggested Fix

The hydration effect should retry on "Session not found" with a short backoff, or the agent backend should await session persistence before responding to hydration queries for deferred sessions. Alternatively, slash commands could be populated from the session snapshot (which already includes slashCommands via Ak()) on every conversation frame update, rather than only during the one-shot hydration effect.

Relevant code locations (zcode.cjs, v3.4.2)

Function Byte offset Role
bSt.discoverCommands ~11053114 Scans command roots, returns discovered commands
fye (listZCodeCustomCommands) ~11146334 Calls discoverCommands, catches errors → []
Ak (listProtocolSlashCommands) ~11230737 Builds protocol slash command list, try/catch silently returns [] on failure

In the renderer (index-GjXEi8_8.js):

  • XWe() hydration effect runs TA()zcodeSessionService → on success calls setSlashCommands(). On failure (.catch()), sets config status to "error" but never retries.
  • lZe() reads slashCommands from the workspace store — returns [] because hydration failed.
  • GZe() renders emptyUnavailable text when slashCommands.length === 0.

Environment

  • ZCode version: 3.4.2 (Desktop)
  • OS: Windows 11 Pro (10.0.26200 x64)
  • Plugin storage root: C:\Users\Brett\.zcode\cli\plugins
  • User config: ~/.zcode/cli/config.json
  • Reproducibility: 100% — every workspace, every new session

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions