Skip to content

service: event seq collision drops session events after config reload #51798

Closed as not planned

Description

@ayushwardhan-iqline

Summary

Editing opencode.jsonc while a session is actively running causes the service to lose session events. Two concurrent writers allocate the same event.seq for one session aggregate, and the second insert fails on UNIQUE(aggregate_id, seq). The affected turn is reported to the model as an error and the event is dropped, leaving the session unable to continue.

Environment

  • opencode version: 2.0.18
  • OS: Linux 6.18.33.2-microsoft-standard-WSL2 feat: compact and other improvements #1 SMP PREEMPT_DYNAMIC Thu Jun 18 21:54:43 UTC 2026 x86_64 (WSL2, networkingMode=mirrored)
  • Terminal: TERM=xterm-256color, TERM_PROGRAM unset, COLORTERM unset, WT_SESSION set (Windows Terminal)
  • Shell: /usr/bin/zsh
  • Install/channel: curl install, latest channel
  • Active plugins: none configured

Reproduction

  1. Start a session and let it run a tool call so the session has in-flight event writes.
  2. While that session is still running, edit the global config at ~/.config/opencode/opencode.jsonc (even a whitespace/comment-only edit).
  3. The service watches ~/.config/opencode with inotify and reloads configuration.
  4. Within ~20 seconds, the running session's event write fails and the turn errors.

Observed twice in a single session:

2026-09-28T07:42:08.607  mtime of ~/.config/opencode/opencode.jsonc
2026-09-28T07:42:09.950  violation #1
2026-09-28T07:42:26.539  violation #2

Both failures are seq=427 on the same session aggregate, from two different event types — which is what makes this look like a sequence-allocation race rather than a duplicate insert:

params: evt_0e6f6d01b001iSAQxlXQDgakGK,ses_f191622cbffe670EoOV4COHAGu,427,message.part.updated.1
params: evt_0e6f710ea001N6MKHZveJfATKn,ses_f191622cbffe670EoOV4COHAGu,427,message.updated.1

Expected Behavior

A configuration reload should not interfere with in-flight session writes. Either the sequence allocator should serialize per aggregate so the second writer takes seq=428, or the insert should retry on conflict.

Actual Behavior

level=ERROR message=process error="Failed query: insert into \"event\" (\"id\", \"aggregate_id\", \"seq\", \"type\", \"data\") values (?, ?, ?, ?, ?)"
  cause: EffectDrizzleQueryError ... (cause: SqlError ... SQLiteError: UNIQUE constraint failed: event.aggregate_id, event.seq)

The failure propagates into Session.updateMessage -> SessionProcessor.cleanup and is surfaced to the model as an UnknownError turn. The session stopped accepting prompts afterward.

Additional Context

  • Reproduced 2 times, both within one session. I have not yet reproduced it from a clean start, so I cannot confirm the config edit is causal rather than coincidental with an unrelated write race — the reload and the collision are tightly correlated in both cases, but n=2 in a single session is weak evidence for causation.
  • The service subscribes to the config directory, so this is reachable without any explicit action beyond editing a file:
    level=INFO message="watcher subscribe" path=/home/xylar/.config/opencode type=directory ignores=3 role=server
    level=INFO message="watcher started" path=/home/xylar/.config/opencode type=directory backend=inotify ignores=3 role=server
    
  • Because sessions are event-sourced, a dropped event is not just a lost log line — it is a gap in the session's state history.
  • No workaround found other than editing config only while no session is running. Restarting the service clears the stuck state.
  • If a config edit legitimately needs to invalidate in-memory state, it would help to know whether that path is meant to be concurrency-safe.

Activity

  1. github-actions commented on Sep 28, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    • #51316: reports concurrent events colliding on the same aggregate sequence with the same SQLite unique-constraint error, leaving the session unusable.
    • #31072: reports a concurrent event sequence-allocation race causing duplicate aggregate sequence numbers (in an earlier implementation).
  2. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the detailed report and logs. I couldn't reproduce this on 2.0.18. A session was running a tool call that streamed output for about 15 seconds, and during that time I made 10 comment-only edits to the watched global opencode.jsonc. Every session event was written in order, the turn finished normally, and the log had no UNIQUE constraint failed errors.

    Something in your logs suggests they may not have come from v2:

    • The colliding event types, message.part.updated.1 and message.updated.1, are v1 event names. In 2.0.18, session events are named session.* (for example session.tool.called or session.step.ended).
    • Session.updateMessage and SessionProcessor.cleanup from the stack trace are v1 code. They don't exist in v2.

    So the failing process may have been a v1 install (opencode-ai 1.x) on the same machine. Could you check:

    1. The output of opencode --version, and of which -a opencode opencode2, from the shell where you start the session.
    2. Whether you have the v1 npm package opencode-ai installed alongside @opencode/cli.
    3. If it does happen on 2.x, the matching lines from the v2 log (they mention session.* event types), plus anything unusual in your setup, such as multiple clients attached to the same service.

    You can reply here, or edit the issue and leave a comment saying you've updated it.

  3. opencodejr commented on Oct 31, 2026

    @opencodejr

    Closing this for now because we haven't heard back. I couldn't reproduce the UNIQUE constraint failed: event.aggregate_id, event.seq error on 2.0.18 by editing the config file while a session was running. Also, the event types and stack frames in your logs (message.part.updated.1, Session.updateMessage, SessionProcessor.cleanup) come from v1, not v2.

    If it happens again on 2.x, please reopen this issue or open a new one. Include the output of opencode --version and which -a opencode opencode2 from the shell where you start the session, plus the v2 log lines (they mention session.* event types). Thanks for the detailed report.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions