ipfs/kubo · critical
embedded downgrade phase failed: %w
Error message
embedded downgrade phase failed: %w
What it means
On the downgrade path, RunHybridMigrations first runs embedded migrations backwards from the current version down to the v16 floor via RunEmbeddedMigrations (before handing off to external migrations for older versions). If that embedded downgrade fails, the error is wrapped as "embedded downgrade phase failed". Downgrades are only attempted when allowDowngrade is true.
Source
Thrown at repo/fsrepo/migrations/migrations.go:476
if err != nil {
return fmt.Errorf("embedded migration phase failed: %w", err)
}
logger.Printf("Hybrid migration completed successfully: v%d → v%d", currentVer, targetVer)
return nil
}
// Case 4: Reverse hybrid migration (≥16 to <16)
// Use embedded migrations for ≥16 steps, then external migrations for <16 steps
logger.Printf("Starting reverse hybrid migration from version %d to %d", currentVer, targetVer)
logger.Print("Using reverse hybrid migration strategy: embedded to v16, then external")
// Phase 1: Use embedded migrations from current version down to v16 (if needed)
if currentVer > embeddedMigrationsMinVersion {
logger.Printf("Phase 1: Embedded downgrade from v%d to v%d", currentVer, embeddedMigrationsMinVersion)
err = RunEmbeddedMigrations(ctx, embeddedMigrationsMinVersion, ipfsDir, allowDowngrade)
if err != nil {
return fmt.Errorf("embedded downgrade phase failed: %w", err)
}
}
// Phase 2: Use external migrations from v16 to target (if needed)
if embeddedMigrationsMinVersion > targetVer {
logger.Printf("Phase 2: External downgrade from v%d to v%d", embeddedMigrationsMinVersion, targetVer)
// Check for external migration binaries in PATH first
migrations, binPaths, err := findMigrations(ctx, embeddedMigrationsMinVersion, targetVer)
if err != nil {
return fmt.Errorf("could not determine external migration paths: %w", err)
}
foundAll := true
for _, migName := range migrations {
if _, exists := binPaths[migName]; !exists {
foundAll = false
breakView on GitHub (pinned to 329838acdf)
Solutions
- Prefer not downgrading: re-install the newer ipfs binary matching the repo version instead of rolling the repo back
- If downgrade is intended, back up the repo first, then re-run with allowDowngrade=true after fixing the underlying I/O error reported by %w
- Check <ipfsDir>/version to see which step failed and run `ipfs fs-repo-migrations -to <ver>` manually for detailed output
- If the newer schema stored data the old version cannot represent, export needed data (ipfs dag/ipns/pin exports) before downgrading
Example fix
// before (downgrade attempted against repo migrated by newer kubo)
err := migrations.RunHybridMigrations(ctx, 15, ipfsPath, true)
// after (align binary with repo version instead of forcing downgrade)
ver, _ := migrations.RepoVersion(ipfsPath)
if ver > 15 {
log.Fatalf("repo v%d requires kubo >= v%d; upgrade the binary instead of downgrading", ver, ver)
}
err = migrations.RunHybridMigrations(ctx, 15, ipfsPath, true) Defensive patterns
Strategy: validation
Validate before calling
ver, err := migrations.RepoVersion(ipfsPath)
if err != nil {
return err
}
if ver > 16 && !allowDowngrade {
return fmt.Errorf("repo v%d is newer than binary target v16; refusing downgrade (set allowDowngrade deliberately)", ver)
}
Type guard
func isDowngradePhaseFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "downgrade phase failed")
}
Try / catch
if err := migrations.RunHybridMigrations(ctx, targetVer, ipfsPath, true); err != nil {
if strings.Contains(err.Error(), "embedded downgrade phase failed") {
return fmt.Errorf("downgrade aborted mid-step; repo may be at an intermediate version — restore backup or re-run: %w", err)
}
return err
}
Prevention
- Prefer matching the binary version to the repo instead of downgrading the repo
- Always back up the repo before any downgrade
- Check <ipfsDir>/version before and after to know the exact state
- Export pins/IPNS keys before downgrading across schema changes
When it happens
Trigger: Calling RunHybridMigrations with targetVer < currentVer and allowDowngrade==true, when currentVer > 16 and RunEmbeddedMigrations(ctx, 16, ipfsDir, allowDowngrade) fails: a rollback migration cannot convert newer repo data, the binary running the daemon is older than the repo, or I/O/context failure mid-step.
Common situations: User downgraded the ipfs binary (e.g. rolled back a release) while the repo was already migrated by a newer version and answered yes to the downgrade prompt; rollback migrations refuse lossy conversions of data written by the newer schema; interrupted downgrade leaves the repo at an intermediate version.
Related errors
- downgrade not allowed from %d to %d
- embedded migration phase failed: %w
- external downgrade phase failed: %w
- abort failed: close: %w, remove: %v
- source field %s does not exist
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/801f18e073b60a47.
Report an issue: GitHub.