{
  "slug": "sqlite-busy-snapshot",
  "term": "SQLITE_BUSY_SNAPSHOT",
  "aliases": [
    "SQLite stale snapshot upgrade"
  ],
  "definition": "SQLITE_BUSY_SNAPSHOT is SQLite's extended result code for a WAL read transaction that cannot become a writer because its snapshot is obsolete.",
  "note": "Code 517 belongs to the SQLITE_BUSY (5) primary family; retain the extended result when diagnosing an upgrade failure. [sqlite-result-codes] In Hesela's constructed schedules, repeating the UPDATE failed even after the other writer had committed, including when it changed a different row; ending the transaction and rereading succeeded. [hesela-upgrade] BEGIN IMMEDIATE moves writer acquisition before the reads but may itself fail to acquire the writer position. [sqlite-transactions] A new transaction does not invalidate values cached by the application: Hesela's separate retry experiment committed an obsolete bound value successfully after rollback, overwriting the other increment. Rereading and recomputing preserved both increments; a revision predicate rejected the stale write with zero affected rows. [hesela-retry-values]",
  "status": "shipping",
  "advantages": [],
  "limitations": [
    {
      "text": "A configured busy timeout is not a mechanism for refreshing the retained snapshot.",
      "citationIds": [
        "sqlite-isolation"
      ]
    },
    {
      "text": "The six-case observation is not a failure-rate or latency study.",
      "citationIds": [
        "hesela-upgrade"
      ]
    },
    {
      "text": "Successful commit and integrity_check do not prove that application intent survived a retry; the four-strategy experiment is a constructed counterexample, not an observed production rate.",
      "citationIds": [
        "hesela-retry-values"
      ]
    }
  ],
  "related": [
    "sqlite-wal-end-mark",
    "checkpoint-starvation",
    "serializability"
  ],
  "supersedes": [],
  "supersededBy": [],
  "firstSeen": null,
  "lastSeen": null,
  "citations": [
    {
      "id": "sqlite-result-codes",
      "title": "SQLite: result and error codes, SQLITE_BUSY_SNAPSHOT (517) and SQLITE_BUSY (5)",
      "url": "https://www.sqlite.org/rescode.html#busy_snapshot",
      "accessed": "2026-10-16"
    },
    {
      "id": "sqlite-transactions",
      "title": "SQLite: DEFERRED, IMMEDIATE and EXCLUSIVE transactions",
      "url": "https://www.sqlite.org/lang_transaction.html",
      "accessed": "2026-10-16"
    },
    {
      "id": "sqlite-isolation",
      "title": "SQLite: isolation and stale read-to-write upgrades",
      "url": "https://www.sqlite.org/isolation.html",
      "accessed": "2026-10-16"
    },
    {
      "id": "hesela-upgrade",
      "title": "Hesela: measured six-case SQLite snapshot-upgrade experiment",
      "url": "https://hesela.dev/research/sqlite-snapshot-upgrade.json",
      "accessed": "2026-10-16"
    },
    {
      "id": "hesela-readers",
      "title": "SQLite WAL checkpoint starvation: success is not completion",
      "url": "https://hesela.com/analyses/sqlite-wal-checkpoint-starvation/#snapshot-upgrade",
      "accessed": "2026-10-16"
    },
    {
      "id": "hesela-retry-values",
      "title": "Hesela: measured retry-value boundaries, cached binding versus recomputation",
      "url": "https://hesela.dev/research/sqlite-retry-values.json",
      "accessed": "2026-10-16"
    }
  ],
  "updated": "2026-10-16"
}
