Skip to content

Race condition in session prompt state management #11699

Closed

Description

@ryan-mt

Summary

The session prompt module has a race condition in its state management that can cause unexpected behavior when multiple concurrent operations access the same session.

Location

packages/opencode/src/session/prompt.ts:239-264

Issue

The start() function has a check-then-act pattern without atomicity:

function start(sessionID: string) {
  const s = state()
  if (s[sessionID]) return  // CHECK
  const controller = new AbortController()
  s[sessionID] = {          // ACT - race condition window between check and act
    abort: controller,
    callbacks: [],
  }
  return controller.signal
}

Between the check at line 241 and the write at line 243, another concurrent call could:

  1. Also pass the check (sees no entry)
  2. Create its own entry
  3. Overwrite the first entry

Additionally, the loop() function at line 267-273 can push to callbacks array while the state is being modified.

Impact

  • Severity: Medium
  • Type: Race Condition
  • Effect:
    • Lost abort controllers
    • Callbacks registered to wrong session
    • Potential undefined access errors

Suggested Fix

Use the existing Lock utility for synchronization:

import { Lock } from "../util/lock"

const sessionLock = new Lock()

async function start(sessionID: string) {
  return await Lock.write(sessionID, async () => {
    const s = state()
    if (s[sessionID]) return undefined
    const controller = new AbortController()
    s[sessionID] = {
      abort: controller,
      callbacks: [],
    }
    return controller.signal
  })
}

Activity

  1. github-actions commented on Feb 2, 2026

    @github-actions
    Contributor

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

    Feel free to ignore if none of these address your specific case.

  2. github-actions commented on Apr 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 90 days of no activity. If the issue is still relevant please open a new one.

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