langchain-ai/deepagents · error · RuntimeError

workspace binding was not persisted for thread {thread_id}

Error message

workspace binding was not persisted for thread {thread_id}

What it means

In `_bind`, after inserting a proposed workspace binding inside a transaction, the code re-reads the row for `thread_id` from `dcode_thread_workspaces`. This RuntimeError is an internal consistency check: the row must exist after the bind attempt; if it does not, persistence failed unexpectedly.

Source

Thrown at libs/code/deepagents_code/workspace.py:248

            (
                thread_id,
                proposed.schema_version,
                proposed.workspace_id,
                proposed.cwd,
                proposed.project_root,
                proposed.generation,
                proposed.resource_key,
                proposed.config_fingerprint,
                proposed.workspace_config_json,
            ),
        )
        row = conn.execute(
            "SELECT * FROM dcode_thread_workspaces WHERE thread_id = ?",
            (thread_id,),
        ).fetchone()
        if row is None:
            msg = f"workspace binding was not persisted for thread {thread_id}"
            raise RuntimeError(msg)
        existing = _row_binding(row)
        if _binding_differs(existing, proposed):
            msg = f"thread {thread_id} is already bound to a different workspace"
            raise WorkspaceConflictError(msg)
        if not existing.config_fingerprint:
            conn.execute(
                """
                UPDATE dcode_thread_workspaces
                SET schema_version = ?, resource_key = ?, config_fingerprint = ?,
                    workspace_config_json = ?
                WHERE thread_id = ? AND config_fingerprint = ''
                """,
                (
                    proposed.schema_version,
                    proposed.resource_key,
                    proposed.config_fingerprint,
                    proposed.workspace_config_json,
                    thread_id,

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Retry the bind operation; this is typically transient
  2. Check for external jobs or tooling deleting rows from `dcode_thread_workspaces`
  3. If reproducible, inspect the database file for corruption and restore/recreate the thread workspaces table

Example fix

// before
conn.execute("DELETE FROM dcode_thread_workspaces")  # external cleanup racing binds
// after
conn.execute("DELETE FROM dcode_thread_workspaces WHERE thread_id IN (SELECT ... expired ...)")
Defensive patterns

Strategy: retry

Try / catch

try:
    await bind_thread_workspace(tid, cwd)
except RuntimeError as exc:
    if "not persisted" in str(exc):
        await asyncio.sleep(0.05)
        await bind_thread_workspace(tid, cwd)

Prevention

When it happens

Trigger: A concurrent transaction deleted the row between insert/upsert and re-select; a database trigger or migration removed rows; a corrupted or externally modified `dcode_thread_workspaces` table.

Common situations: Another process (or a cleanup job) purging thread rows while a bind is in flight; running against a shared SQLite database with manual row deletion; bugs in custom tooling that manipulates the table.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/1f7c96d586715348. Report an issue: GitHub.