containerd/containerd · error
can't load base OCI spec %q: %w
Error message
can't load base OCI spec %q: %w
What it means
When a base OCI spec file is configured (base_spec_file in the CRI runtime config), runtimeSpec loads it via c.LoadOCISpec and wraps any load failure with this error. It means the base runtime spec JSON could not be read or parsed into an oci.Spec.
Source
Thrown at internal/cri/server/container_create.go:519
HostPath: src,
SelinuxRelabel: true,
UidMappings: uidMappings,
GidMappings: gidMappings,
})
}
return mounts
}
// runtimeSpec returns a default runtime spec used in cri-containerd.
func (c *criService) runtimeSpec(id string, platform imagespec.Platform, baseSpecFile string, opts ...oci.SpecOpts) (*runtimespec.Spec, error) {
// GenerateSpec needs namespace.
ctx := util.NamespacedContext()
container := &containers.Container{ID: id}
if baseSpecFile != "" {
baseSpec, err := c.LoadOCISpec(baseSpecFile)
if err != nil {
return nil, fmt.Errorf("can't load base OCI spec %q: %w", baseSpecFile, err)
}
spec := oci.Spec{}
if err := util.DeepCopy(&spec, &baseSpec); err != nil {
return nil, fmt.Errorf("failed to clone OCI spec: %w", err)
}
// Fix up cgroups path
applyOpts := append([]oci.SpecOpts{oci.WithNamespacedCgroup()}, opts...)
if err := oci.ApplyOpts(ctx, nil, container, &spec, applyOpts...); err != nil {
return nil, fmt.Errorf("failed to apply OCI options: %w", err)
}
return &spec, nil
}
spec, err := oci.GenerateSpecWithPlatform(ctx, nil, platforms.Format(platform), container, opts...)View on GitHub (pinned to 4246446a2b)
Solutions
- Verify the path in containerd config (plugins.'io.containerd.grpc.v1.cri'.containerd.base_spec_file) exists and is readable by containerd
- Validate the JSON with `jq . <file>` or `oci-runtime-tool validate --file <file>` and fix syntax/schema errors
- Generate a known-good baseline: `runc spec > /etc/containerd/base-spec.json` and point base_spec_file at it
- Remove base_spec_file from config to fall back to the default generated spec, then restart containerd
Example fix
// before (config.toml) [plugins."io.containerd.grpc.v1.cri".containerd] base_spec_file = "/etc/containerd/basespec.json" # file missing // after [plugins."io.containerd.grpc.v1.cri".containerd] base_spec_file = "/etc/containerd/base-spec.json" # exists, valid JSON
Defensive patterns
Strategy: validation
Validate before calling
// preflight the base spec file before (re)starting containerd
package main
import ("encoding/json", "fmt", "os")
func checkBaseSpec(path string) error {
b, err := os.ReadFile(path)
if err != nil { return err }
var s struct { OCIVersion string `json:"ociVersion"` }
if err := json.Unmarshal(b, &s); err != nil { return fmt.Errorf("invalid JSON: %w", err) }
if s.OCIVersion == "" { return fmt.Errorf("missing ociVersion") }
return nil
} Try / catch
if err != nil && strings.Contains(err.Error(), "can't load base OCI spec") {
// fall back: run with default spec (remove base_spec_file) after validating the file
log.Printf("base spec unusable: %v", err)
} Prevention
- Validate base_spec_file with jq/oci-runtime-tool in config management (Ansible/Helm pre-start hook)
- Always start from `runc spec` output and edit minimally
- Keep base spec files under version control with CI JSON-schema validation
- Verify the path is absolute and readable by the containerd service user before restart
When it happens
Trigger: baseSpecFile is set in the containerd CRI config and LoadOCISpec fails because the file does not exist, is unreadable, or contains invalid JSON/an invalid OCI spec schema.
Common situations: Typo'd or deleted base_spec_file path in containerd config.toml; hand-edited spec JSON with syntax errors; file created after containerd started with wrong permissions; spec generated for an incompatible OCI spec version.
Related errors
- invalid `stats_retention_period`: %w
- invalid stream idle timeout: %w
- failed to generate container %q spec: %w
- failed to clone OCI spec: %w
- failed to apply OCI options: %w
AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02).
Data as JSON: /api/errors/5b1045da543e4393.
Report an issue: GitHub.