Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions devlog/2026-08-13_fix-dcp-context-handled-error/REQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# REQ — Fix __DCP_CONTEXT_HANDLED__ Error Leak (Issue #296)

## Problem

`/acp` commands throw `Error: __DCP_CONTEXT_HANDLED__` which leaks to the opencode error log. In opencode 1.18.18, this produces `level=ERROR` entries for every `/acp` invocation.

## Root Cause

The command handler in `hooks.ts` threw `new Error("__DCP_CONTEXT_HANDLED__")` after handling `/acp` commands. This sentinel was meant to abort command processing, but opencode catches and logs it as an error.

## Fix

Replace both `throw new Error("__DCP_CONTEXT_HANDLED__")` with `return`. The commands deliver output via `sendIgnoredMessage` (which writes directly to the session via `client.session.prompt`), so the hook can return normally without any side effects.
13 changes: 13 additions & 0 deletions devlog/2026-08-13_fix-dcp-context-handled-error/WORKLOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# WORKLOG — Fix __DCP_CONTEXT_HANDLED__ Error Leak

## Changes

`lib/hooks.ts`: Replaced 2× `throw new Error("__DCP_CONTEXT_HANDLED__")` with `return` (lines 295, 299).
`tests/hooks-permission.test.ts`: Added regression test verifying handler returns normally.

## Verification

- TypeScript: 0 errors
- Tests: 977 pass, 0 fail
- Build: 391.50 KB
- Deployed locally
3 changes: 1 addition & 2 deletions lib/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,10 @@ export function createCommandExecuteHandler(
const sub = input.arguments?.trim().toLowerCase()
if (sub === "stats" || sub === "status") {
await handleStatsCommand(commandCtx)
throw new Error("__DCP_CONTEXT_HANDLED__")
return
}

await handleContextCommand(commandCtx)
throw new Error("__DCP_CONTEXT_HANDLED__")
}
}
}
Expand Down
26 changes: 25 additions & 1 deletion tests/hooks-permission.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,32 @@ test("command execute exits after effective permission resolves to deny", async
assert.deepEqual(output.parts, [])
})

test("command execute returns normally (no __DCP_CONTEXT_HANDLED__ throw) — issue #296", async () => {
let sessionMessagesCalls = 0
const output = { parts: [] as any[] }
const handler = createCommandExecuteHandler(
{
session: {
messages: async () => {
sessionMessagesCalls += 1
return { data: [] }
},
},
} as any,
createTestRegistry(createSessionState()),
new Logger(false),
buildConfig("allow"),
"/tmp",
{ global: undefined, agents: {} },
)

await handler({ command: "acp", sessionID: "session-1", arguments: "context" }, output)

assert.equal(sessionMessagesCalls, 1)
})

test("text complete strips hallucinated metadata tags", async () => {
const output = { text: "alpha <dcp>beta</dcp> omega" }
const output = { text: "alpha omega" }
const handler = createTextCompleteHandler()

await handler({ sessionID: "session-1", messageID: "message-1", partID: "part-1" }, output)
Expand Down
Loading