{"record":{"id":"5d1a8cd361fed78d","repo":"Tencent/WeKnora","slug":"sandbox-docker-backend-requires-an-image","errorCode":null,"errorMessage":"sandbox: docker backend requires an image","messagePattern":"sandbox: docker backend requires an image","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/sandbox/docker_remote_client.go","lineNumber":158,"sourceCode":"\tapi dockerEngineAPI,\n\tsettings dockerRuntimeSettings,\n) *DockerRemoteClient {\n\tadapter := &DockerRemoteClient{api: api, settings: settings}\n\tif settings.IdleTTL > 0 {\n\t\tadapter.sweeper = newDockerIdleSweeper(adapter, settings.IdleTTL)\n\t}\n\treturn adapter\n}\n\n// dockerSettingsFromConfig projects Config, applying the built-in defaults for\n// every value the workspace config leaves unset.\nfunc dockerSettingsFromConfig(cfg *Config) (dockerRuntimeSettings, error) {\n\tif cfg == nil {\n\t\treturn dockerRuntimeSettings{}, errors.New(\"sandbox: docker client requires a config\")\n\t}\n\timage := strings.TrimSpace(cfg.DockerImage)\n\tif image == \"\" {\n\t\treturn dockerRuntimeSettings{}, errors.New(\"sandbox: docker backend requires an image\")\n\t}\n\tsettings := dockerRuntimeSettings{\n\t\tImage:       image,\n\t\tCPULimit:    cfg.DockerCPULimit,\n\t\tMemoryBytes: cfg.DockerMemoryBytes,\n\t\tPidsLimit:   cfg.DockerPidsLimit,\n\t\tNetworkMode: strings.TrimSpace(cfg.DockerNetworkMode),\n\t\tRuntime:     strings.TrimSpace(cfg.DockerRuntime),\n\t\tIdleTTL:     cfg.DockerIdleTTL,\n\t\tHTTPTimeout: cfg.DockerHTTPTimeout,\n\t\tEndpoint: dockerEndpoint{\n\t\t\tHost:         strings.TrimSpace(cfg.DockerHost),\n\t\t\tTLSCertPath:  strings.TrimSpace(cfg.DockerTLSCertPath),\n\t\t\tAllowPrivate: cfg.AllowPrivateEndpoints,\n\t\t\tTimeout:      cfg.DockerHTTPTimeout,\n\t\t},\n\t}\n\tif settings.CPULimit <= 0 {","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/sandbox/docker_remote_client.go#L140-L176","documentation":"After applying defaults, dockerSettingsFromConfig requires cfg.DockerImage to name a container image; the Docker backend cannot create a sandbox without one, so an empty (or whitespace-only) DockerImage is rejected. This is a fail-fast validation so misconfiguration surfaces at client construction rather than at sandbox Create time.","triggerScenarios":"Constructing a Docker remote client via NewDockerRemoteClient or NewDockerRemoteClientForCheck while cfg.DockerImage is unset or contains only whitespace.","commonSituations":"Workspace config file omits the docker image key; environment variable substitution resolves to empty; a config struct is built programmatically and only limits are set; TestDockerSettingsRequireImage exercises exactly this path.","solutions":["Set cfg.DockerImage to a valid image reference (e.g. \"ubuntu:24.04\") before constructing the client","Check the workspace config file / env vars actually populate DockerImage (trailing whitespace is trimmed, so \"  \" still fails)","Use the library's default config constructor if one exists so the built-in default image is applied"],"exampleFix":"// before\ncfg := &sandbox.Config{DockerCPULimit: 2}\n// after\ncfg := &sandbox.Config{DockerImage: \"ubuntu:24.04\", DockerCPULimit: 2}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(cfg.DockerImage) == \"\" {\n    return errors.New(\"docker sandbox requires an image before client construction\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set DockerImage (defaults help: use the library's default config builder)","Validate the whole docker settings block (image + limits) at config-load time","Trim and check string config values; whitespace-only values behave like empty"],"tags":["go","sandbox","docker","config","missing-image"],"backgroundTag":"missing-configuration","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}