{"record":{"id":"1cafda2bdec84a86","repo":"ipfs/kubo","slug":"could-not-read-migration-config-w","errorCode":null,"errorMessage":"could not read migration config: %w","messagePattern":"could not read migration config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"repo/fsrepo/migrations/migrations.go","lineNumber":399,"sourceCode":"\t\t\treturn fmt.Errorf(\"could not determine migration paths: %w\", err)\n\t\t}\n\n\t\tfoundAll := true\n\t\tfor _, migName := range migrations {\n\t\t\tif _, exists := binPaths[migName]; !exists {\n\t\t\t\tfoundAll = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif foundAll {\n\t\t\treturn runMigrationsFromPath(ctx, migrations, binPaths, ipfsDir, logger, false)\n\t\t}\n\n\t\t// Fall back to network download (original behavior)\n\t\tmigrationCfg, err := ReadMigrationConfig(ipfsDir, \"\")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"could not read migration config: %w\", err)\n\t\t}\n\n\t\t// Use existing RunMigration which handles network downloads properly (HTTPS only for legacy migrations)\n\t\tfetcher, err := GetMigrationFetcher(migrationCfg.DownloadSources, GetDistPathEnv(CurrentIpfsDist), nil)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to get migration fetcher: %w\", err)\n\t\t}\n\t\tdefer fetcher.Close()\n\t\treturn RunMigration(ctx, fetcher, targetVer, ipfsDir, allowDowngrade)\n\t}\n\n\t// Case 3: Hybrid migration (current < 16, target ≥ 16)\n\tif needsExternal && needsEmbedded {\n\t\tlogger.Printf(\"Starting hybrid migration from version %d to %d\", currentVer, targetVer)\n\t\tlogger.Print(\"Using hybrid migration strategy: external to v16, then embedded\")\n\n\t\t// Phase 1: Use external migrations to get to v16\n\t\tlogger.Printf(\"Phase 1: External migration from v%d to v%d\", currentVer, embeddedMigrationsMinVersion)","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/repo/fsrepo/migrations/migrations.go#L381-L417","documentation":"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.","triggerScenarios":"ReadMigrationConfig(ipfsDir, \"\") fails because the migrations config file exists but is unreadable or malformed (invalid syntax), or an I/O error occurs reading it.","commonSituations":"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.","solutions":["Inspect and fix the migrations config file in IPFS_PATH (correct syntax, readable permissions)","Delete the custom migration config to fall back to defaults (dist.ipfs.tech)","Check file ownership: match the user running the daemon","Test parsing manually by re-creating the config from the documented format"],"exampleFix":"// before\n{\"DownloadSources\": [\"https://dist.ipfs.tech\",]}  // trailing comma: parse error\n// after\n{\"DownloadSources\": [\"https://dist.ipfs.tech\"]}","handlingStrategy":"validation","validationCode":"cfgPath := filepath.Join(ipfsDir, \"migrations\")\nif data, err := os.ReadFile(cfgPath); err == nil {\n    var cfg map[string]json.RawMessage\n    if err := json.Unmarshal(data, &cfg); err != nil {\n        log.Fatalf(\"invalid migration config %s: %v\", cfgPath, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"could not read migration config\") {\n    return fmt.Errorf(\"fix or delete the migrations config file in IPFS_PATH: %w\", err)\n}","preventionTips":["Validate the migrations config JSON after hand-editing","Match file ownership with the daemon user","Remove custom config to fall back to defaults","Keep config minimal — only override what you need"],"tags":["migrations","config","parse-error"],"backgroundTag":"migration-config-invalid","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}