dagger/dagger · error

close db before import-wipe

Error message

close db before import-wipe

What it means

When importing persisted state back into the freshly opened cache fails, NewCache attempts a wipe-and-cold-start recovery. Before wiping it must close both DBs; if closeCacheDBs fails, this "close db before import-wipe" error is returned (joined with the close error), aborting startup instead of performing the recovery wipe.

Source

Thrown at dagql/cache.go:473

			return nil, errors.Join(fmt.Errorf("close db before wipe"), closeErr)
		}
		if err := wipeSQLiteFiles(dbPath); err != nil {
			return nil, fmt.Errorf("wipe unclean persistence db: %w", err)
		}

		db, persistDB, err = prepareCacheDBs(ctx, dbPath)
		if err != nil {
			return nil, err
		}
		c.sqlDB = db
		c.pdb = persistDB
	}
	if err := c.importPersistedState(ctx); err != nil {
		c.persistenceResetReason = CachePersistenceResetImportFailure
		c.tracePersistStoreWipedImportFailure(ctx, err)
		slog.Warn("dagql persistence import failed; wiping and cold-starting", "err", err)
		if closeErr := closeCacheDBs(db, c.pdb); closeErr != nil {
			return nil, errors.Join(fmt.Errorf("close db before import-wipe"), closeErr)
		}
		if err := wipeSQLiteFiles(dbPath); err != nil {
			return nil, fmt.Errorf("wipe persistence db after import failure: %w", err)
		}
		db, persistDB, err = prepareCacheDBs(ctx, dbPath)
		if err != nil {
			return nil, err
		}
		c.sqlDB = db
		c.pdb = persistDB
	}

	if err := c.pdb.UpsertMeta(ctx, persistdb.MetaKeySchemaVersion, cachePersistenceSchemaVersion); err != nil {
		if closeErr := closeCacheDBs(db, c.pdb); closeErr != nil {
			return nil, errors.Join(fmt.Errorf("set persistence schema version: %w", err), closeErr)
		}
		return nil, fmt.Errorf("set persistence schema version: %w", err)
	}

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Stop any other dagger/engine process sharing the cache path, then restart so the close+wipe can succeed.
  2. Check free disk space and filesystem health before restarting.
  3. Delete the persistence files manually while the engine is stopped and let the next start cold-initialize.
  4. Ensure the same Dagger version is used for the cache dir (avoid version mixing on shared volumes).

Example fix

// before: import fails, close also fails (second instance holds lock)
$ dagger run ...  # aborts
// after
$ kill <other-engine-pid>; rm -f /var/lib/dagger/cache.db*; restart dagger
Defensive patterns

Strategy: try-catch

Validate before calling

// only one instance, writable dir, sane timeout before an import-heavy init
func preflight(dbPath string) error {
	if err := unix.Access(dbPath, unix.W_OK); err != nil { return err }
	return os.MkdirAll(filepath.Dir(dbPath+".lock"), 0o755) // + lockfile discipline
}

Try / catch

c, err := dagql.NewCache(ctx, dbPath, sm, gc)
if err != nil && strings.Contains(err.Error(), "close db before import-wipe") {
	// another holder blocked the recovery close: clear and retry once
	os.Remove(dbPath); os.Remove(dbPath+"-wal"); os.Remove(dbPath+"-shm")
	c, err = dagql.NewCache(ctx, dbPath, sm, gc)
}
if err != nil { return err }

Prevention

When it happens

Trigger: c.importPersistedState(ctx) returns an error (corrupt/incompatible persisted data, parse failure, context cancelled), then closeCacheDBs(db, c.pdb) also returns an error during the recovery path.

Common situations: Persistence snapshot written by an older/newer Dagger version with incompatible format; truncated cache file after crash; recovery running on a disk that is full or has a locked DB (another instance attached); context deadline exceeded during long import.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/9b88bf82af489f68. Report an issue: GitHub.