Summary
The ACP adapter appears to return a successful stopReason: "end_turn" even when the underlying assistant message contains an internal error.
This was observed while testing with Fabriqa / Fabriqa.ai acting as the ACP client. Fabriqa finalized the turn from the ACP end_turn result, so provider/session errors that remained internal appeared as a blank assistant response.
This is problematic for ACP clients because end_turn means the agent completed the turn normally. If the model/provider/session processor failed, the client needs a protocol-visible failure, not only an internal session.error event or stderr/log output.
Why this matters
ACP clients communicate with the agent over JSON-RPC. Stderr/logs are diagnostic only and should not be required for correctness.
If a session/prompt turn fails due to provider/model/session error, the ACP adapter should surface that through the ACP/JSON-RPC channel. Returning successful end_turn with no useful assistant content causes clients to finalize blank or misleading assistant messages.
ACP references:
Source-level evidence
In packages/opencode/src/session/processor.ts, failures are captured on the assistant message:
ctx.assistantMessage.error = error
yield* bus.publish(Session.Event.Error, {
sessionID: ctx.assistantMessage.sessionID,
error: ctx.assistantMessage.error,
})
But in packages/opencode/src/acp/agent.ts, the ACP session/prompt path does not appear to inspect that error:
const response = await this.sdk.session.prompt(...)
const msg = response.data?.info
await sendUsageUpdate(...)
return {
stopReason: "end_turn" as const,
usage: msg ? buildUsage(msg) : undefined,
_meta: {},
}
So an assistant message with msg.error can still be mapped to a successful ACP end_turn.
Expected behavior
If response.data?.info.error is present, the ACP adapter should not return a normal successful end_turn.
It should either:
- return a JSON-RPC error response to the
session/prompt request, or
- send a user-visible ACP update explaining the error before ending the turn.
Additionally, the adapter should guarantee that all pending session/update notifications are flushed before returning the session/prompt response. This is related to the existing ordering issue where end_turn can arrive before remaining agent_message_chunk notifications:
#17505
Impact
Clients such as Fabriqa, agent-shell, or other ACP hosts may finalize the turn as successful before receiving the actual content or before learning that the turn failed. In the provider-error case, this can produce a blank assistant response with no visible error.
P.S. This report and issue is AI generated but not AI slop. It was manually reviewed by a human over long turns and checked against local logs/source to ensure this is a valid issue.
Summary
The ACP adapter appears to return a successful
stopReason: "end_turn"even when the underlying assistant message contains an internal error.This was observed while testing with Fabriqa / Fabriqa.ai acting as the ACP client. Fabriqa finalized the turn from the ACP
end_turnresult, so provider/session errors that remained internal appeared as a blank assistant response.This is problematic for ACP clients because
end_turnmeans the agent completed the turn normally. If the model/provider/session processor failed, the client needs a protocol-visible failure, not only an internalsession.errorevent or stderr/log output.Why this matters
ACP clients communicate with the agent over JSON-RPC. Stderr/logs are diagnostic only and should not be required for correctness.
If a
session/promptturn fails due to provider/model/session error, the ACP adapter should surface that through the ACP/JSON-RPC channel. Returning successfulend_turnwith no useful assistant content causes clients to finalize blank or misleading assistant messages.ACP references:
Source-level evidence
In
packages/opencode/src/session/processor.ts, failures are captured on the assistant message:But in
packages/opencode/src/acp/agent.ts, the ACPsession/promptpath does not appear to inspect that error:So an assistant message with
msg.errorcan still be mapped to a successful ACPend_turn.Expected behavior
If
response.data?.info.erroris present, the ACP adapter should not return a normal successfulend_turn.It should either:
session/promptrequest, orAdditionally, the adapter should guarantee that all pending
session/updatenotifications are flushed before returning thesession/promptresponse. This is related to the existing ordering issue whereend_turncan arrive before remainingagent_message_chunknotifications:#17505
Impact
Clients such as Fabriqa, agent-shell, or other ACP hosts may finalize the turn as successful before receiving the actual content or before learning that the turn failed. In the provider-error case, this can produce a blank assistant response with no visible error.
P.S. This report and issue is AI generated but not AI slop. It was manually reviewed by a human over long turns and checked against local logs/source to ensure this is a valid issue.