{"record":{"id":"a6069ce5e005cd0f","repo":"GoogleContainerTools/skaffold","slug":"upgrading-pipelines-failed-s","errorCode":null,"errorMessage":"upgrading pipelines failed: %s","messagePattern":"upgrading pipelines failed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/schema/util/upgrade_pipelines.go","lineNumber":36,"sourceCode":"\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n)\n\ntype pipelineUpgrader struct {\n\toldConfig reflect.Value\n\tnewConfig reflect.Value\n\tupgrade   func(o, n interface{}) error\n}\n\nfunc UpgradePipelines(oldConfig, newConfig interface{}, upgrade func(o, n interface{}) error) (err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tswitch x := r.(type) {\n\t\t\tcase string:\n\t\t\t\terr = fmt.Errorf(\"upgrading pipelines failed: %s\", x)\n\t\t\tcase error:\n\t\t\t\terr = x\n\t\t\tdefault:\n\t\t\t\terr = errors.New(\"unknown panic\")\n\t\t\t}\n\t\t}\n\t}()\n\n\tupgrader := pipelineUpgrader{\n\t\toldConfig: reflect.Indirect(reflect.ValueOf(oldConfig)),\n\t\tnewConfig: reflect.Indirect(reflect.ValueOf(newConfig)),\n\t\tupgrade:   upgrade,\n\t}\n\n\tif err := upgrader.mainPipeline(); err != nil {\n\t\treturn err\n\t}\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/schema/util/upgrade_pipelines.go#L18-L54","documentation":"UpgradePipelines converts a skaffold config to the next schema version by upgrading the main pipeline and each profile pipeline. It wraps the whole upgrade in a recover() so a panic inside any versioned Upgrade() (e.g. Go nil-dereference on a malformed config) becomes a controlled error. This message is produced when the recovered panic value is a plain string; error panics are passed through and anything else becomes 'unknown panic'.","triggerScenarios":"Calling UpgradePipelines(oldConfig, newConfig, upgrade) where the upgrade function panics with panic(\"some string\") — typically a nil map/pointer access or an explicit string panic inside a versioned schema Upgrade().","commonSituations":"Upgrading configs with missing sections (nil Build/Deploy pointers) that a versioned Upgrade method dereferences without nil checks; third-party or older schema code that panics on unexpected field shapes.","solutions":["Read the recovered string message to find which pipeline field panicked, then fix or prune that section of the source config","Add nil guards in the custom upgrade function so it cannot panic on partially-populated configs","Validate/repair the source config with skaffold's validation before upgrading"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if err := config.Validate(); err != nil { return err } // pre-validate before upgrade","typeGuard":null,"tryCatchPattern":"if err := util.UpgradePipelines(old, new, upgradeFn); err != nil {\n\tvar target *schema.UnsupportedFieldError\n\tif errors.As(err, &target) { /* handle */ }\n\treturn fmt.Errorf(\"pipeline upgrade failed: %w\", err)\n}","preventionTips":["Pre-validate configs before upgrading","Write upgrade functions that nil-check all pointer/map fields","Avoid panic(string) in upgrade code; return errors instead"],"tags":["go","panic-recovery","schema-upgrade"],"backgroundTag":"schema-upgrade-panic","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}