{"record":{"id":"009426a9089e6d3c","repo":"pulumi/pulumi","slug":"update-timeout-changed-expected-v","errorCode":null,"errorMessage":"update timeout changed (expected %v)","messagePattern":"update timeout changed \\(expected (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resource/deploy/plan.go","lineNumber":625,"sourceCode":"\tdefault:\n\t\texpected := \"no value\"\n\t\tif rp.Goal.DeleteBeforeReplace != nil {\n\t\t\texpected = strconv.FormatBool(*rp.Goal.DeleteBeforeReplace)\n\t\t}\n\t\treturn fmt.Errorf(\"deleteBeforeReplace changed (expected %v)\", expected)\n\t}\n\n\t// Check that the import ID is identical.\n\tif rp.Goal.ID != programGoal.ID {\n\t\treturn fmt.Errorf(\"importID changed (expected %v)\", rp.Goal.ID)\n\t}\n\n\t// Check that the timeouts are identical.\n\tswitch {\n\tcase rp.Goal.CustomTimeouts.Create != programGoal.CustomTimeouts.Create:\n\t\treturn fmt.Errorf(\"create timeout changed (expected %v)\", rp.Goal.CustomTimeouts.Create)\n\tcase rp.Goal.CustomTimeouts.Update != programGoal.CustomTimeouts.Update:\n\t\treturn fmt.Errorf(\"update timeout changed (expected %v)\", rp.Goal.CustomTimeouts.Update)\n\tcase rp.Goal.CustomTimeouts.Delete != programGoal.CustomTimeouts.Delete:\n\t\treturn fmt.Errorf(\"delete timeout changed (expected %v)\", rp.Goal.CustomTimeouts.Delete)\n\tcase rp.Goal.CustomTimeouts.Read != programGoal.CustomTimeouts.Read:\n\t\treturn fmt.Errorf(\"read timeout changed (expected %v)\", rp.Goal.CustomTimeouts.Read)\n\t}\n\n\t// Check that the ignoreChanges sets are identical.\n\tif message, changed := rp.diffStringSets(rp.Goal.IgnoreChanges, programGoal.IgnoreChanges); changed {\n\t\treturn fmt.Errorf(\"ignoreChanges changed: %v\", message)\n\t}\n\n\t// Check that the additionalSecretOutputs sets are identical.\n\tif message, changed := rp.diffPropertyKeys(\n\t\trp.Goal.AdditionalSecretOutputs, programGoal.AdditionalSecretOutputs); changed {\n\t\treturn fmt.Errorf(\"additionalSecretOutputs changed: %v\", message)\n\t}\n\n\t// Check that the dependencies match.","sourceCodeStart":607,"sourceCodeEnd":643,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/pkg/resource/deploy/plan.go#L607-L643","documentation":"checkGoal compares CustomTimeouts between plan and program; this branch fires when the update timeout recorded in the plan differs from the program's current value.","triggerScenarios":"Replaying a saved plan after changing `customTimeouts: { update: \"20m\" }` on the resource, or adding/removing the update timeout after the plan was saved.","commonSituations":"Extending update timeouts for long-running in-place updates (e.g. cluster upgrades) while a plan is pending; inconsistent timeout edits across environments sharing a plan.","solutions":["Restore the update timeout to the planned value, or regenerate the plan","Re-save the plan if the timeout change is intentional","Discard the saved plan and apply without a plan","Keep timeout config synchronized with any pending plan files in CI"],"exampleFix":"// before: update timeout changed after plan saved\n{ customTimeouts: { update: \"10m\" } }\n// after: match planned goal\n{ customTimeouts: { update: \"20m\" } }","handlingStrategy":"validation","validationCode":"if curTimeouts.Update != planTimeouts.Update {\n\treturn errors.New(\"update timeout drifted from saved plan\")\n}","typeGuard":null,"tryCatchPattern":"if err := up(plan); err != nil && strings.Contains(err.Error(), \"update timeout changed\") {\n\treturn regeneratePlan()\n}","preventionTips":["Batch timeout increases with plan regeneration","Don't edit CustomTimeouts while a plan is pending in CI","Regenerate the plan whenever update behavior tuning changes","Store plan files with the exact commit that produced them"],"tags":["pulumi-plan","timeouts","plan-validation","go"],"backgroundTag":"plan-goal-drift","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}