ipfs/kubo · error

could not read migration config: %w

Error message

could not read migration config: %w

What it means

When migration binaries aren't available locally and the code falls back to network download, it reads the migration config file via ReadMigrationConfig. A failure reading/parsing that config aborts with this wrapped error.

Source

Thrown at repo/fsrepo/migrations/migrations.go:399

			return fmt.Errorf("could not determine migration paths: %w", err)
		}

		foundAll := true
		for _, migName := range migrations {
			if _, exists := binPaths[migName]; !exists {
				foundAll = false
				break
			}
		}

		if foundAll {
			return runMigrationsFromPath(ctx, migrations, binPaths, ipfsDir, logger, false)
		}

		// Fall back to network download (original behavior)
		migrationCfg, err := ReadMigrationConfig(ipfsDir, "")
		if err != nil {
			return fmt.Errorf("could not read migration config: %w", err)
		}

		// Use existing RunMigration which handles network downloads properly (HTTPS only for legacy migrations)
		fetcher, err := GetMigrationFetcher(migrationCfg.DownloadSources, GetDistPathEnv(CurrentIpfsDist), nil)
		if err != nil {
			return fmt.Errorf("failed to get migration fetcher: %w", err)
		}
		defer fetcher.Close()
		return RunMigration(ctx, fetcher, targetVer, ipfsDir, allowDowngrade)
	}

	// Case 3: Hybrid migration (current < 16, target ≥ 16)
	if needsExternal && needsEmbedded {
		logger.Printf("Starting hybrid migration from version %d to %d", currentVer, targetVer)
		logger.Print("Using hybrid migration strategy: external to v16, then embedded")

		// Phase 1: Use external migrations to get to v16
		logger.Printf("Phase 1: External migration from v%d to v%d", currentVer, embeddedMigrationsMinVersion)

View on GitHub (pinned to 329838acdf)

Solutions

  1. Inspect and fix the migrations config file in IPFS_PATH (correct syntax, readable permissions)
  2. Delete the custom migration config to fall back to defaults (dist.ipfs.tech)
  3. Check file ownership: match the user running the daemon
  4. Test parsing manually by re-creating the config from the documented format

Example fix

// before
{"DownloadSources": ["https://dist.ipfs.tech",]}  // trailing comma: parse error
// after
{"DownloadSources": ["https://dist.ipfs.tech"]}
Defensive patterns

Strategy: validation

Validate before calling

cfgPath := filepath.Join(ipfsDir, "migrations")
if data, err := os.ReadFile(cfgPath); err == nil {
    var cfg map[string]json.RawMessage
    if err := json.Unmarshal(data, &cfg); err != nil {
        log.Fatalf("invalid migration config %s: %v", cfgPath, err)
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "could not read migration config") {
    return fmt.Errorf("fix or delete the migrations config file in IPFS_PATH: %w", err)
}

Prevention

When it happens

Trigger: ReadMigrationConfig(ipfsDir, "") fails because the migrations config file exists but is unreadable or malformed (invalid syntax), or an I/O error occurs reading it.

Common situations: Hand-edited migration config files with syntax errors; wrong permissions on the config file; config created by a different user (root) than the daemon user.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/1cafda2bdec84a86. Report an issue: GitHub.