kubernetes/kops · error
failed to get info for server %q: %w
Error message
failed to get info for server %q: %w
What it means
After issuing Shutdown, deleteServer polls client.GetByID up to 30 times waiting for the server to reach status 'off'; this error is thrown when GetByID returns an error or a nil server during that poll loop.
Source
Thrown at upup/pkg/fi/cloudup/hetzner/cloud.go:276
return err
}
// deleteServer shuts down and deletes the given server
func deleteServer(c *hetznerCloudImplementation, id int64) error {
client := c.ServerClient()
ctx := context.TODO()
server := &hcloud.Server{ID: id}
_, _, err := client.Shutdown(ctx, server)
if err != nil {
return fmt.Errorf("failed to stop server %q: %w", strconv.FormatInt(id, 10), err)
}
for i := 1; i <= 30; i++ {
server, _, err := client.GetByID(ctx, id)
if err != nil || server == nil {
return fmt.Errorf("failed to get info for server %q: %w", strconv.FormatInt(id, 10), err)
}
if server.Status == hcloud.ServerStatusOff {
break
}
time.Sleep(time.Second * 5)
}
_, err = client.Delete(ctx, server)
if err != nil {
return fmt.Errorf("failed to delete server %q: %w", strconv.FormatInt(id, 10), err)
}
return nil
}
func (c *hetznerCloudImplementation) DetachInstance(instance *cloudinstances.CloudInstance) error {View on GitHub (pinned to 4c8573c808)
Solutions
- Re-check whether the server exists; treat nil server as already gone and proceed to delete/reconcile
- Back off / add rate-limit handling in polling (the loop sleeps 5s per iteration but can still trip limits)
- Retry the whole DeleteInstance operation after transient failures
- Verify token validity and network stability during long-running operations
Example fix
// before
if err != nil || server == nil {
return fmt.Errorf("failed to get info for server %q: %w", strconv.FormatInt(id, 10), err)
}
// after
if err != nil {
return fmt.Errorf("failed to get info for server %q: %w", strconv.FormatInt(id, 10), err)
}
if server == nil {
return nil // server already gone, nothing to delete
} Defensive patterns
Strategy: retry
Validate before calling
// before polling, confirm the server exists and is shutting down
server, _, err := client.GetByID(ctx, id)
if err == nil && server != nil && server.Status == hcloud.ServerStatusOff {
return nil
} Type guard
func serverReachedStatus(client *hcloud.ServerClient, id int64, want hcloud.ServerStatus) (bool, error) {
s, _, err := client.GetByID(context.TODO(), id)
if err != nil {
return false, err
}
if s == nil {
return true, nil // gone: nothing to wait for
}
return s.Status == want, nil
} Try / catch
server, _, err := client.GetByID(ctx, id)
if err != nil {
var hErr *hcloud.Error
if errors.As(err, &hErr) && hErr.Code == hcloud.ErrorCodeRateLimit {
time.Sleep(hErr.RateLimit.RetryAfter())
continue
}
return fmt.Errorf("failed to get info for server %q: %w", strconv.FormatInt(id, 10), err)
} Prevention
- Handle rate limits inside long poll loops
- Treat nil server during polling as already-deleted rather than erroring
- Use context timeouts instead of fixed 30-iteration loops
- Monitor API health during large rolling updates
When it happens
Trigger: The server is deleted out-of-band during the wait (GetByID returns nil), the API token becomes invalid mid-loop, rate limiting kicks in after repeated polling, or a network error occurs while polling.
Common situations: Slow shutdown exceeding the 150s poll window combined with an external deletion, hcloud API flakiness, or rate limit from frequent GetByID calls on large rolling updates.
Related errors
- failed to list servers: %w
- failed to stop server %q: %w
- failed to delete server %q: %w
- failed to list ssh keys: %w
- failed to list networks: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/f6c06750d8820656.
Report an issue: GitHub.