Before submitting
Area
apps/server — provider adapter (OpenCodeAdapter.rollbackThread)
Summary
When reverting a number of turns equal to or greater than the total number of assistant turns in a conversation, rollbackThread calls session.revert() without a messageID in the body. The OpenCode server rejects this with 400 BadRequest: "Expected object, got undefined".
Root Cause
In apps/server/src/provider/Layers/OpenCodeAdapter.ts:1386-1392:
const targetIndex = assistantMessages.length - numTurns - 1;
const target = targetIndex >= 0 ? assistantMessages[targetIndex] : null;
yield* runOpenCodeSdk("session.revert", () =>
context.client.session.revert({
sessionID: context.openCodeSessionId,
...(target ? { messageID: target.info.id } : {}), // {} when target is null
}),
);
When numTurns >= assistantMessages.length, targetIndex is < 0, so target is null. The spread produces { sessionID: "…" } with no messageID. The SDK strips the empty body and sends a POST with no body. The OpenCode server requires messageID in the body and returns a 400.
Example: 2 assistant turns, reverting 2 turns → targetIndex = 2 - 2 - 1 = -1 → target = null → no messageID.
Reproduction Steps
- Start a conversation with exactly 1 assistant turn (1 user prompt + 1 assistant response).
- Right-click the assistant message and choose "Revert to this point" (or otherwise trigger a revert that removes all assistant turns).
- Observe the error in the server logs:
OpenCodeRuntimeError:
at opencode.session.revert
…
[cause]: Error: Expected object, got undefined
[cause]: Error: {"body":{"name":"BadRequest","data":{"message":"Expected object, got undefined","kind":"Payload"}},"status":400}
Expected behavior
Reverting all assistant turns should succeed (reverting to before the first assistant message), or should be handled gracefully with a user-facing error.
Actual behavior
session.revert call fails with a 400, causing an unhandled error in the rollback flow.
Stack trace (from nightly)
OpenCodeRuntimeError:
at opencode.session.revert (apps/server/dist/bin.mjs:26670:16)
at rollbackThread (apps/server/dist/bin.mjs:26402:26)
at rollbackConversation
at handleRevertRequested
at processDomainEvent
[cause]: Error: Expected object, got undefined
at wrapClientError (@opencode-ai/sdk/dist/error-interceptor.js:26:16)
at request (@opencode-ai/sdk/dist/v2/gen/client/client.gen.js:169:37)
[cause]: Error: {"body":{"name":"BadRequest","data":{"message":"Expected object, got undefined","kind":"Payload"}},"status":400}
Fix direction
In OpenCodeAdapter.rollbackThread, when target is null (reverting before the first assistant message), the code must still provide a valid messageID — potentially the user message that initiated the conversation, or handle this edge case with an alternative approach.
Version
0.0.25-nightly.20260515.295
Environment
macOS
Before submitting
Area
apps/server — provider adapter (
OpenCodeAdapter.rollbackThread)Summary
When reverting a number of turns equal to or greater than the total number of assistant turns in a conversation,
rollbackThreadcallssession.revert()without amessageIDin the body. The OpenCode server rejects this with400 BadRequest: "Expected object, got undefined".Root Cause
In
apps/server/src/provider/Layers/OpenCodeAdapter.ts:1386-1392:When
numTurns >= assistantMessages.length,targetIndexis< 0, sotargetisnull. The spread produces{ sessionID: "…" }with nomessageID. The SDK strips the empty body and sends a POST with no body. The OpenCode server requiresmessageIDin the body and returns a 400.Example: 2 assistant turns, reverting 2 turns →
targetIndex = 2 - 2 - 1 = -1→target = null→ nomessageID.Reproduction Steps
Expected behavior
Reverting all assistant turns should succeed (reverting to before the first assistant message), or should be handled gracefully with a user-facing error.
Actual behavior
session.revertcall fails with a 400, causing an unhandled error in the rollback flow.Stack trace (from nightly)
Fix direction
In
OpenCodeAdapter.rollbackThread, whentargetisnull(reverting before the first assistant message), the code must still provide a validmessageID— potentially the user message that initiated the conversation, or handle this edge case with an alternative approach.Version
0.0.25-nightly.20260515.295
Environment
macOS