{"record":{"id":"fbf5ba99db8474b1","repo":"dagger/dagger","slug":"failed-to-get-oci-state-for-container-s-w","errorCode":null,"errorMessage":"failed to get OCI state for container %s: %w","messagePattern":"failed to get OCI state for container (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/engineutil/linux_namespace.go","lineNumber":436,"sourceCode":"// ShutdownGlobalNamespaceWorkerPool gracefully shuts down the global namespace worker pool\n// This should be called during application shutdown\nfunc ShutdownGlobalNamespaceWorkerPool() {\n\tif globalNSWorkerPool != nil {\n\t\tglobalNSWorkerPool.Stop()\n\t}\n}\n\n// getContainerPID retrieves the PID of a container using libcontainer\nfunc getContainerPID(containerID string) (int, error) {\n\t// Load the container using libcontainer\n\tcontainer, err := libcontainer.Load(\"/run/runc\", containerID)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"failed to create libcontainer factory: %w\", err)\n\t}\n\n\tstate, err := container.OCIState()\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"failed to get OCI state for container %s: %w\", containerID, err)\n\t}\n\n\tif state.Pid == 0 {\n\t\treturn 0, fmt.Errorf(\"container %s has no running process\", containerID)\n\t}\n\n\treturn state.Pid, nil\n}\n","sourceCodeStart":418,"sourceCodeEnd":445,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/engine/engineutil/linux_namespace.go#L418-L445","documentation":"After loading the container, getContainerPID calls container.OCIState() to read the runtime state (including the init process PID). This error means reading the OCI state failed — the container's state.json may be unreadable, the process metadata (init pid fd / cgroup) may have vanished, or the container is mid-teardown.","triggerScenarios":"container.OCIState() returns an error, typically when the container is in a transient state (created/stopped), its init process already exited, or /run/runc/<id>/state.json is stale.","commonSituations":"Race with container shutdown: runc state exists but the process is gone so pidfd/stat lookups fail; corrupted state file; version mismatch between libcontainer library and the runc that created the state.","solutions":["Check the container is in \"running\" state (runc state <id>) before querying","Handle the exit race: retry the lookup or treat it as container-exited","Ensure the libcontainer library version matches the runc that created the state directory","Read the PID from /run/runc/<id>/state.json directly as a fallback"],"exampleFix":"// before\nstate, err := container.OCIState()\nif err != nil { return 0, err }\n// after\nstate, err := container.OCIState()\nif err != nil {\n    if st, statErr := container.State(); statErr == nil && st.Status == libcontainer.Stopped {\n        return 0, fmt.Errorf(\"container %s already stopped: %w\", containerID, err)\n    }\n    return 0, err\n}","handlingStrategy":"retry","validationCode":"st, err := container.State()\nif err == nil && st.Status != libcontainer.Running {\n    return fmt.Errorf(\"container not running (status=%s); skip PID lookup\", st.Status)\n}","typeGuard":null,"tryCatchPattern":"pid, err := getContainerPID(containerID)\nif err != nil && strings.Contains(err.Error(), \"failed to get OCI state\") {\n    time.Sleep(50 * time.Millisecond) // tolerate exit race\n    pid, err = getContainerPID(containerID)\n}","preventionTips":["Check container status is \"running\" before reading OCIState","Treat OCIState failures during teardown as container-exited, not fatal","Keep libcontainer library version aligned with installed runc"],"tags":["runc","libcontainer","oci","race-condition"],"backgroundTag":"container-state-not-found","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}