unslothai/unsloth · error · ResearchConflictError
This thread already has a Deep Research run
Error message
This thread already has a Deep Research run
What it means
ResearchConflictError raised while creating a Deep Research run: inserting into research_thread_claims hit sqlite3.IntegrityError, and a follow-up SELECT confirmed a claim row already exists for that thread_id — the table enforces one active research run per thread (unique thread_id). The insert+check pattern distinguishes this from an unrelated integrity failure (which re-raises bare).
Source
Thrown at studio/backend/storage/research_runs_db.py:158
created_at: int | None = None,
) -> dict:
created = created_at or now_ms()
conn = get_connection()
try:
conn.execute("BEGIN IMMEDIATE")
try:
conn.execute(
"INSERT INTO research_thread_claims (owner_subject, thread_id, created_at) "
"VALUES (?, ?, ?)",
(owner_subject, thread_id, created),
)
except sqlite3.IntegrityError as exc:
claim = conn.execute(
"SELECT 1 FROM research_thread_claims WHERE thread_id=?",
(thread_id,),
).fetchone()
if claim is not None:
raise ResearchConflictError("This thread already has a Deep Research run") from exc
raise
if assistant_message_id:
message = conn.execute(
"SELECT * FROM chat_messages WHERE id=?", (assistant_message_id,)
).fetchone()
metadata = {
"researchRunId": run_id,
"researchStatus": "planning",
"researchPlanRevision": 0,
"serverManaged": True,
}
if message is None:
conn.execute(
"""INSERT INTO chat_messages
(id, thread_id, parent_id, role, content_json, metadata_json, created_at)
VALUES (?, ?, ?, 'assistant', '[]', ?, ?)""",
(
assistant_message_id,View on GitHub (pinned to 203007d190)
Solutions
- Wait for the existing run to finish (or cancel it) before starting another in the same thread.
- Disable the Start button while a run is active; key it off the thread's researchStatus metadata.
- On catching this conflict, re-fetch the thread state and surface the existing run instead of erroring to the user.
Example fix
// before
button.onclick = () => api.startResearch(threadId); // double-click => conflict
// after
if (thread.researchStatus && !isTerminal(thread.researchStatus)) return;
button.disabled = true;
try { await api.startResearch(threadId); } finally { button.disabled = false; } Defensive patterns
Strategy: validation
Validate before calling
// Only start a run when the thread has none active
const status = thread.metadata?.researchStatus;
const terminal = ['completed', 'failed', 'cancelled'].includes(status);
if (status && !terminal) throw new ConflictError('This thread already has a Deep Research run');
await api.startResearch(threadId); Type guard
function threadHasActiveRun(t: Thread): boolean {
const s = t.metadata?.researchStatus;
return !!s && !['completed', 'failed', 'cancelled'].includes(s);
} Try / catch
try { await createRun(threadId, ...); }
catch (e) {
if (e?.name === 'ResearchConflictError' || /already has a Deep Research run/.test(e?.message)) {
const state = await fetchThreadState(threadId); // adopt the live run
showExistingRun(state.activeRun);
} else throw e;
} Prevention
- Disable the Start control while researchStatus is non-terminal
- Make run creation idempotent per thread via a client request id
- On network retry, check for the existing run before re-submitting
When it happens
Trigger: Two 'start research' requests for the same chat thread racing (double-click, retry, or two tabs); starting a new run while a previous run is still active/unfinished in that thread; a client that does not wait for the terminal state before issuing the next run.
Common situations: Double-submit from a flaky network retry; UI lets the user click Start again before the run reaches a terminal state; background poller that re-triggers creation.
Related errors
- Assistant message does not match this research run
- Authorization callback was already used.
- A diffusion load is already in progress.
- deadline reached while pacing before {method} {_redact_url(u
- job already running
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/9ee31c61934efbcc.
Report an issue: GitHub.