vxcontrol/pentagi · error
failed to create volume: %w
Error message
failed to create volume: %w
What it means
When the client was constructed without a host directory (hostDir == ""), RunContainer creates a named Docker volume named <containerName>-data to back the /work mount instead of a bind mount. If VolumeCreate fails the container is marked Failed and the error "failed to create volume: %w" is returned. This wraps a daemon error — inspect the cause (named volume name conflicts, driver errors, storage limits).
Source
Thrown at backend/pkg/docker/client.go:331
hostConfig = &container.HostConfig{}
}
// prevent containers from auto-starting after OS or docker daemon restart
// because on startup they create docker.sock directory for DinD if it's enabled
hostConfig.RestartPolicy = container.RestartPolicy{
Name: container.RestartPolicyOnFailure,
MaximumRetryCount: 5,
}
if hostDir == "" {
volumeName, err := dc.client.VolumeCreate(ctx, client.VolumeCreateOptions{
Name: fmt.Sprintf("%s%s", containerName, WorkerVolumeNameSuffix),
Driver: "local",
Labels: dc.labels,
})
if err != nil {
defer updateContainerInfo(database.ContainerStatusFailed, "")
return database.Container{}, fmt.Errorf("failed to create volume: %w", err)
}
hostDir = volumeName.Volume.Name
}
hostConfig.Binds = append(hostConfig.Binds, fmt.Sprintf("%s:%s", hostDir, WorkFolderPathInContainer))
if dc.inside {
// The socket is empty when DOCKER_INSIDE_HOST designates a daemon endpoint
// instead; binding "" would produce a malformed mount spec.
if dc.socket != "" {
hostConfig.Binds = append(hostConfig.Binds, fmt.Sprintf("%s:%s", dc.socket, defaultDockerSocketPath))
}
// Point the sandbox's Docker CLI at the designated daemon.
config.Env = append(config.Env, dc.insideEnv...)
// TLS material is mounted read-only at the same path on both sides so the
// injected DOCKER_CERT_PATH resolves unchanged inside the container.
if dc.insideCertPath != "" {View on GitHub (pinned to ea665308ba)
Solutions
- Inspect the wrapped cause; check for an existing conflicting volume: docker volume ls / docker volume inspect <name>-data, remove it if stale (docker volume rm).
- Free disk space on the Docker storage host (docker system df, docker volume prune).
- Ensure container names are unique per flow/run so the <name>-data volume name does not collide with a live volume.
- If labels/tenants changed, delete the old volume created with the previous labels before rerunning.
- Check daemon logs (journalctl -u docker) for volume driver errors.
Example fix
# before: retry loop reuses same container name → same volume name
name := fmt.Sprintf("tool-%s", toolName) # collides with existing volume tool-x-data
# after
name := fmt.Sprintf("tool-%s-flow-%d", toolName, flowID) # unique volume per flow Defensive patterns
Strategy: try-catch
Validate before calling
volName := containerName + "-data"
vols, err := cli.VolumeList(ctx, client.VolumeListOptions{})
if err == nil {
for _, v := range vols.Volumes {
if v.Name == volName {
// exists: decide to reuse or remove before VolumeCreate
_ = cli.VolumeRemove(ctx, volName, false)
}
}
} Try / catch
_, err := dc.RunContainer(ctx, name, ctype, flowID, cfg, hostCfg)
var derr *client.VolumeCreateError // or match on message
if err != nil && strings.Contains(err.Error(), "failed to create volume") {
_ = cli.VolumeRemove(context.Background(), name+"-data", true)
return retryOnce() // recreate volume with fresh state
} Prevention
- Generate unique container names per flow/run so derived volume names never collide.
- Schedule docker volume prune during maintenance windows.
- Monitor disk usage on the Docker storage host.
- Keep container names within Docker's naming charset (avoid odd characters from tool inputs).
- Check daemon volume driver health when running on non-default storage backends.
When it happens
Trigger: dc.client.VolumeCreate fails: a volume with the same name already exists but is in use with incompatible labels, the 'local' volume driver errors (bad volume options, storage backend full), daemon read-only in an insecure sandbox, or the volume name contains characters rejected by the daemon.
Common situations: Container names reused across runs (e.g. retried flow producing the same <name>-data volume) combined with label/tenant changes; disk full on the Docker volume host; running with a restricted daemon (Docker rootless quota exceeded); name containing invalid characters from an injected tool name.
Related errors
- Internal
- failed to get flow screenshot: %w
- failed to stop flow %d: %w
- failed to create extension %q in schema %q (a privileged use
- failed to initialize docker client: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/2d43dacd504f2b59.
Report an issue: GitHub.