Summary
When a slash command (e.g. any /ctx_* magic-context command) triggers a session upgrade, the handler throws the string sentinel CTX-SESSION-UPGRADE_HANDLED__ as an internal control-flow signal. This sentinel is not caught before it crosses the OpenCode plugin hook boundary, so OpenCode's plugin executor treats it as an unhandled exception and surfaces it as a visible error in the TUI.
Root cause
Magic-context catches the sentinel in its own internal flow to stop further processing, but the throw propagates back through the OpenCode command.execute.before hook dispatch chain before being caught. OpenCode sees an exception it did not originate and renders it in the TUI error surface.
// Observed in OpenCode TUI:
Error: CTX-SESSION-UPGRADE_HANDLED__
at ...magic-context/dist/index.js:...
The command.execute.before hook return contract expects either a return value or a silently handled promise. A thrown string that OpenCode doesn't recognise as a sentinel violates that contract.
Reproduction
- Have an active OpenCode session with extended thinking or a long enough conversation that magic-context considers a session upgrade.
- Run any magic-context slash command (e.g.
/ctx_reduce, /handoff, /ctx_expand).
- Observe the TUI immediately displays:
Error: CTX-SESSION-UPGRADE_HANDLED__.
Expected behaviour
The sentinel must not escape the magic-context plugin boundary. Two valid fixes:
Option A — catch-and-silence at the hook exit:
// In the command.execute.before handler wrapper
try {
await innerHandler(input, output);
} catch (err) {
if (isMagicContextSentinel(err)) return; // swallow — upgrade handled internally
throw err; // re-throw real errors
}
Option B — replace throw with a return signal:
Replace the sentinel throw with a structured return value or a shared flag that the hook reads, eliminating the exception entirely.
Option A is the minimal fix; Option B is cleaner long-term.
Impact
Every slash command invocation that triggers a session upgrade produces a spurious error in the TUI, eroding user trust and making real errors harder to spot.
Severity
P1 — cosmetic but high-visibility; appears on every magic-context slash command invocation under upgrade conditions.
Summary
When a slash command (e.g. any
/ctx_*magic-context command) triggers a session upgrade, the handler throws the string sentinelCTX-SESSION-UPGRADE_HANDLED__as an internal control-flow signal. This sentinel is not caught before it crosses the OpenCode plugin hook boundary, so OpenCode's plugin executor treats it as an unhandled exception and surfaces it as a visible error in the TUI.Root cause
Magic-context catches the sentinel in its own internal flow to stop further processing, but the throw propagates back through the OpenCode
command.execute.beforehook dispatch chain before being caught. OpenCode sees an exception it did not originate and renders it in the TUI error surface.The
command.execute.beforehook return contract expects either a return value or a silently handled promise. A thrown string that OpenCode doesn't recognise as a sentinel violates that contract.Reproduction
/ctx_reduce,/handoff,/ctx_expand).Error: CTX-SESSION-UPGRADE_HANDLED__.Expected behaviour
The sentinel must not escape the magic-context plugin boundary. Two valid fixes:
Option A — catch-and-silence at the hook exit:
Option B — replace throw with a return signal:
Replace the sentinel throw with a structured return value or a shared flag that the hook reads, eliminating the exception entirely.
Option A is the minimal fix; Option B is cleaner long-term.
Impact
Every slash command invocation that triggers a session upgrade produces a spurious error in the TUI, eroding user trust and making real errors harder to spot.
Severity
P1 — cosmetic but high-visibility; appears on every magic-context slash command invocation under upgrade conditions.