Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

Failed COMMIT leaves transaction open and breaks subsequent transactions

Fechada
#307 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
4/5
Tempo estimado
3-5 dias
Facilidade para iniciantes
68/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Pouca atividade
Stack de tecnologia
react-native, sqlite, typescript
Domínio
databases

Direção de pesquisa

Leia packages/react-native-nitro-sqlite/src/operations/transaction.ts, especialmente os caminhos de commit e rollback nas linhas indicadas, e compare o comportamento do commit manual com o comportamento do commit automático. Adicione a cobertura de regressão em um teste Harness usando o reproduzidor de chave estrangeira adiada; considera-se concluído quando o erro de commit original é preservado, a linha inserida está ausente, os erros de rollback continuam visíveis quando aplicável e uma segunda transação é bem-sucedida na mesma conexão.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

area:runtime bug

Summary

When COMMIT fails, transaction() marks the transaction as finished before executing the SQL. The catch block then skips rollback, leaving SQLite inside the failed transaction. A later transaction on the same connection fails with cannot start a transaction within a transaction.

Verified on main at ad8b835 (v9.7.0).

Code evidence

transaction.ts#L44-L52 sets isFinished = true before execute(dbName, 'COMMIT').

If that execute throws, control reaches transaction.ts#L81-L90. The rollback guard is if (!isFinished), so rollback is skipped.

SQLite can legitimately fail COMMIT, including for deferred foreign-key constraints, I/O errors, and busy/locking conditions. A failed commit can leave the transaction active.

Smallest reliable reproducer

const db = open({ name: 'commit-failure.sqlite' })
db.execute('PRAGMA foreign_keys = ON')
db.execute('CREATE TABLE parent (id INTEGER PRIMARY KEY)')
db.execute(`
  CREATE TABLE child (
    parent_id INTEGER
      REFERENCES parent(id)
      DEFERRABLE INITIALLY DEFERRED
  )
`)

await expect(
  db.transaction(async (tx) => {
    tx.execute('INSERT INTO child(parent_id) VALUES (?)', [404])
  }),
).rejects.toThrow(/FOREIGN KEY constraint failed/)

// Expected: starts cleanly after the failed transaction was rolled back.
// Observed: "cannot start a transaction within a transaction".
await db.transaction(async (tx) => {
  tx.execute('SELECT 1')
})

The underlying SQLite sequence is deterministic:

PRAGMA foreign_keys = ON;
CREATE TABLE parent(id INTEGER PRIMARY KEY);
CREATE TABLE child(parent_id INTEGER REFERENCES parent(id) DEFERRABLE INITIALLY DEFERRED);
BEGIN;
INSERT INTO child(parent_id) VALUES (404);
COMMIT; -- FOREIGN KEY constraint failed
BEGIN;  -- cannot start a transaction within a transaction

Impact

One commit-time failure poisons the connection for later writes. Callers receive the original commit error, but the library's transaction abstraction no longer restores its documented all-or-nothing/usable-connection invariant.

Acceptance criteria

  • Do not transition to a committed/finalized state until COMMIT succeeds.
  • On commit failure, attempt rollback while the transaction remains active.
  • Preserve the original commit failure; if rollback also fails, expose both errors without replacing the primary cause.
  • Model transaction state explicitly enough to distinguish active, committed, rolled back, and failed-finalization states.
  • Keep manual commit() and automatic commit behavior consistent.

Regression-test target

A Harness test using a deferred foreign-key violation that asserts:

  1. The first transaction rejects with the commit-time constraint error.
  2. Its inserted row is absent.
  3. A second transaction on the same connection begins and commits successfully.
Linguagem predominante
C
Estrelas
579
Forks
53
Merge médio
2d 3h
PRs com merge (30d)
70

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de margelo/react-native-nitro-sqlite

Todas as issues de margelo/react-native-nitro-sqlite

Issues semelhantes

Mais issues de C

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.