GoogleContainerTools/skaffold · error

STATUSCHECK_CONTAINER_RESTARTING

STATUSCHECK_CONTAINER_RESTARTING

Error message

container %s is backing off waiting to restart

What it means

Raised when a container's Waiting state has reason CrashLoopBackOff (code STATUSCHECK_CONTAINER_RESTARTING): the container keeps crashing and kubelet is backing off before restarting it. Skaffold fetches logs from the last attempt so the original failure is visible.

Solutions

  1. Read the captured logs (or kubectl logs <pod> --previous -c <container>) to find the original crash cause and fix it.
  2. Check liveness/readiness probes: overly aggressive initialDelaySeconds/periodSeconds can kill slow-starting apps; tune them.
  3. Verify required env vars, secrets, config maps, and dependency endpoints are present and reachable.
  4. kubectl describe pod to confirm restartCount and reason, then fix the command/args or image entrypoint.

Example fix

// before: liveness probe kills slow starter
// livenessProbe: {httpGet: {path: /healthz, port: 8080}, initialDelaySeconds: 1}
// after
// livenessProbe: {httpGet: {path: /healthz, port: 8080}, initialDelaySeconds: 30, failureThreshold: 5}
Defensive patterns

Strategy: try-catch

Validate before calling

if cs.State.Waiting != nil && cs.State.Waiting.Reason == "CrashLoopBackOff" { prev, _ := client.CoreV1().Pods(ns).GetLogs(pod.Name, &v1.PodLogOptions{Container: cs.Name, Previous: true}).Stream(ctx); dump(prev) }

Type guard

func isCrashLooping(cs v1.ContainerStatus) bool { return cs.State.Waiting != nil && cs.State.Waiting.Reason == "CrashLoopBackOff" }

Try / catch

sc, logs, err := getContainerStatus(pod, cs); if sc == proto.StatusCode_STATUSCHECK_CONTAINER_RESTARTING { return fmt.Errorf("crash loop, last logs:\n%s", strings.Join(logs, "\n")) }

Prevention

When it happens

Trigger: extractErrorMessageFromWaitingContainerStatus matches crashLoopBackOff in the Waiting reason, calls getPodLogs, and returns 'container <name> is backing off waiting to restart'; reached from getContainerStatus/getPodStatus.

Common situations: App crashes at startup (bad config, missing env var/secret, unreachable dependency), failing liveness probes restarting a healthy-but-slow app, wrong command/args, port conflicts, exit-on-error scripts.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/60a88a5552651a21. Report an issue: GitHub.

Appendix: source

Thrown at pkg/diag/validator/validator.go:369

			return p.ae.Message
		}
	}
	return fmt.Sprintf(actionableMessage, p.namespace, p.name)
}

func extractErrorMessageFromWaitingContainerStatus(po *v1.Pod, c v1.ContainerStatus) (proto.StatusCode, []string, error) {
	// Extract meaning full error out of container statuses.
	switch c.State.Waiting.Reason {
	case podInitializing:
		// container is waiting to run. This could be because one of the init containers is
		// still not completed
		return proto.StatusCode_STATUSCHECK_POD_INITIALIZING, nil, nil
	case containerCreating:
		return proto.StatusCode_STATUSCHECK_CONTAINER_CREATING, nil, fmt.Errorf("creating container %s", c.Name)
	case crashLoopBackOff:
		// TODO, in case of container restarting, return the original failure reason due to which container failed.
		sc, l := getPodLogs(po, c.Name, proto.StatusCode_STATUSCHECK_CONTAINER_RESTARTING)
		return sc, l, fmt.Errorf("container %s is backing off waiting to restart", c.Name)
	case ImagePullErr, ImagePullBackOff, ErrImagePullBackOff:
		return proto.StatusCode_STATUSCHECK_IMAGE_PULL_ERR, nil, fmt.Errorf("container %s is waiting to start: %s can't be pulled", c.Name, c.Image)
	case runContainerError:
		match := runContainerRe.FindStringSubmatch(c.State.Waiting.Message)
		if len(match) != 0 {
			return proto.StatusCode_STATUSCHECK_RUN_CONTAINER_ERR, nil, fmt.Errorf("container %s in error: %s", c.Name, trimSpace(match[3]))
		}
	}
	log.Entry(context.TODO()).Debugf("Unknown waiting reason for container %q: %v", c.Name, c.State)
	return proto.StatusCode_STATUSCHECK_CONTAINER_WAITING_UNKNOWN, nil, fmt.Errorf("container %s in error: %v", c.Name, c.State.Waiting)
}

func newPodStatus(n string, ns string, p string) *podStatus {
	return &podStatus{
		name:      n,
		namespace: ns,
		phase:     p,
		ae: proto.ActionableErr{

View on GitHub (pinned to a1189de023)