kubernetes/kops · error
spotinst: failed to update ocean: %v
Error message
spotinst: failed to update ocean: %v
What it means
kOps failed while pushing an updated Ocean cluster spec to the Spotinst API during `kops update cluster`. The Ocean already exists, so the `Ocean().Update` call returned an error and it is wrapped verbatim; the root cause is in the inner message (validation rejection, concurrent modification, auth, API outage).
Source
Thrown at upup/pkg/fi/cloudup/spotinsttasks/ocean.go:1141
klog.Warningf("Not all changes applied to Ocean %q: %v", *e.Name, changes)
}
if !changed {
klog.V(2).Infof("No changes detected in Ocean %q", *e.Name)
return nil
}
klog.V(2).Infof("Updating Ocean %q (config: %s)", *e.Name, stringutil.Stringify(ocean))
// Wrap the raw object as an Ocean.
oc, err := spotinst.NewOcean(cloud.ProviderID(), ocean)
if err != nil {
return err
}
// Update an existing Ocean.
if err := cloud.Spotinst().Ocean().Update(context.Background(), oc); err != nil {
return fmt.Errorf("spotinst: failed to update ocean: %v", err)
}
return nil
}
type terraformOcean struct {
Name *string `cty:"name"`
ControllerClusterID *string `cty:"controller_id"`
Region *string `cty:"region"`
InstanceTypesWhitelist []string `cty:"whitelist"`
InstanceTypesBlacklist []string `cty:"blacklist"`
SubnetIDs []*terraformWriter.Literal `cty:"subnet_ids"`
AutoScaler *terraformAutoScaler `cty:"autoscaler"`
Tags []*terraformKV `cty:"tags"`
MinSize *int64 `cty:"min_size"`
MaxSize *int64 `cty:"max_size"`
DesiredCapacity *int64 `cty:"desired_capacity"`View on GitHub (pinned to 4c8573c808)
Solutions
- Inspect the wrapped `%v` message for the concrete Spotinst API error code and address that first.
- Confirm the Ocean still exists in the Spotinst console; if it was deleted out-of-band, recreate it or remove/recreate the kOps-managed resource.
- Avoid immutable field changes (VPC, region) on an existing Ocean — create a new Ocean/cluster instead.
- Verify Spotinst credentials and re-run `kops update cluster` if the API was temporarily unavailable.
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: confirm the Ocean still exists before updating
if _, err := spotinstClient.Ocean().Get(ctx, oceanID); err != nil {
return fmt.Errorf("ocean %s missing; recreate before update: %w", oceanID, err)
} Try / catch
err := runKopsUpdate(ctx)
if err != nil && strings.Contains(err.Error(), "failed to update ocean") {
log.Printf("spotinst update rejected: %v", err) // inner message has the API reason
return err
} Prevention
- Do not change immutable Ocean fields (region, VPC) on an existing cluster.
- Keep Spotinst tokens rotated in sync with kOps configuration.
- Diff `kops update cluster` output before applying to catch rejected spec changes early.
When it happens
Trigger: Running `kops update cluster` against an existing Spotinst Ocean when the generated Ocean spec change is rejected: incompatible field change (e.g. region/VPC immutable), Spotinst API 4xx/5xx, expired token, or the Ocean was deleted out-of-band so the update target no longer exists.
Common situations: Changing node instance types, min/max size, or launch specification on a live cluster; stale Spotinst credentials after token rotation; Ocean deleted in the Spotinst console while kOps still tracks it.
Related errors
- spotinst: failed to create ocean: %v
- error listing resource record sets: %w
- describing instance for arn %q
- error building ssh key: %v
- error building load balancers: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/e1944e7f03e7545a.
Report an issue: GitHub.