{"record":{"id":"7bb1177b0b264991","repo":"containerd/containerd","slug":"container-is-already-in-starting-state","errorCode":null,"errorMessage":"container is already in starting state","messagePattern":"container is already in starting state","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/cri/server/container_start.go","lineNumber":224,"sourceCode":"\t)\n\n\treturn &runtime.StartContainerResponse{}, nil\n}\n\n// setContainerStarting sets the container into starting state. In starting state, the\n// container will not be removed or started again.\nfunc setContainerStarting(container containerstore.Container) error {\n\treturn container.Status.Update(func(status containerstore.Status) (containerstore.Status, error) {\n\t\t// Return error if container is not in created state.\n\t\tif status.State() != runtime.ContainerState_CONTAINER_CREATED {\n\t\t\treturn status, fmt.Errorf(\"container is in %s state\", criContainerStateToString(status.State()))\n\t\t}\n\t\t// Do not start the container when there is a removal in progress.\n\t\tif status.Removing {\n\t\t\treturn status, errors.New(\"container is in removing state, can't be started\")\n\t\t}\n\t\tif status.Starting {\n\t\t\treturn status, errors.New(\"container is already in starting state\")\n\t\t}\n\t\tstatus.Starting = true\n\t\treturn status, nil\n\t})\n}\n\n// resetContainerStarting resets the container starting state on start failure. So\n// that we could remove the container later.\nfunc resetContainerStarting(container containerstore.Container) error {\n\treturn container.Status.Update(func(status containerstore.Status) (containerstore.Status, error) {\n\t\tstatus.Starting = false\n\t\treturn status, nil\n\t})\n}\n\n// createContainerLoggers creates container loggers and return write closer for stdout and stderr.\nfunc (c *criService) createContainerLoggers(logPath string, tty bool) (stdout io.WriteCloser, stderr io.WriteCloser, err error) {\n\tif logPath != \"\" {","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/containerd/containerd/blob/4246446a2bf7d03837b0244118d858799393bd80/internal/cri/server/container_start.go#L206-L242","documentation":"The CRI start path sets `Starting = true` inside an atomic status update; if a previous StartContainer on the same container already set that flag and is still running, a second start is rejected to prevent two concurrent starts of one container.","triggerScenarios":"Two concurrent StartContainer calls for the same container ID; a retried start after a client timeout while the first start is still in flight inside the status update closure in internal/cri/server/container_start.go.","commonSituations":"kubelet retry loops issuing duplicate starts; a CRI client with aggressive timeouts retrying a slow start; duplicate events from a controller reconciler.","solutions":["Wait for the first start to complete (poll ContainerStatus for RUNNING) instead of retrying immediately.","Deduplicate start requests per container ID in the caller.","Increase client timeout so slow starts are not retried while in flight."],"exampleFix":"// before\nclient.StartContainer(ctx, id) // retry while first start still running\n// after\nerr := client.StartContainer(ctx, id)\nif err != nil && strings.Contains(err.Error(), \"already in starting state\") {\n  return nil // first start still in progress; wait instead\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isAlreadyStarting(err error) bool { return err != nil && strings.Contains(err.Error(), \"already in starting state\") }","tryCatchPattern":"if err := client.StartContainer(ctx, id); err != nil {\n  if isAlreadyStarting(err) {\n    return nil // first start in progress; poll for RUNNING instead\n  }\n  return err\n}","preventionTips":["Single-flight start requests per container ID","Use generous timeouts for start to avoid premature retries","Poll ContainerStatus for RUNNING instead of re-issuing start"],"tags":["container-lifecycle","race-condition","cri"],"backgroundTag":"container-concurrent-operation-conflict","analyzedSha":"4246446a2bf7d03837b0244118d858799393bd80","analyzedAt":"2026-09-02T00:14:43.053Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}