{"record":{"id":"220a8572942c1341","repo":"Tencent/WeKnora","slug":"cube-api-create-sandbox-empty-sandboxid","errorCode":null,"errorMessage":"cube api: create sandbox: empty sandboxID","messagePattern":"cube api: create sandbox: empty sandboxID","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sandbox/cube_remote_client.go","lineNumber":514,"sourceCode":"\t\t\tAllowPublicTraffic: network.AllowPublicTraffic,\n\t\t\tAllowOut:           append([]string(nil), network.AllowOut...),\n\t\t\tDenyOut:            append([]string(nil), network.DenyOut...),\n\t\t},\n\t}\n\tif action != \"\" {\n\t\topts.Extra = map[string]any{\n\t\t\t\"lifecycle\": map[string]any{\n\t\t\t\t\"onTimeout\":  string(action),\n\t\t\t\t\"autoResume\": autoResume,\n\t\t\t},\n\t\t}\n\t}\n\tsb, err := c.client.Create(ctx, opts)\n\tif err != nil {\n\t\treturn nil, normalizeCubeError(\"Create\", err)\n\t}\n\tif sb == nil || sb.SandboxID == \"\" {\n\t\treturn nil, errors.New(\"cube api: create sandbox: empty sandboxID\")\n\t}\n\tlogCubeSandboxCreated(ctx, c, sb, network.AllowPublicTraffic)\n\treturn &cubeRemoteHandle{\n\t\tsb:       sb,\n\t\tmetadata: cloneMetadata(request.Metadata),\n\t}, nil\n}\n\nfunc (c *CubeRemoteClient) Connect(\n\tctx context.Context,\n\tsandboxID string,\n) (RemoteSandboxHandle, error) {\n\tif strings.TrimSpace(sandboxID) == \"\" {\n\t\treturn nil, cubeInvalidRequest(\"Connect\", \"sandbox ID is required\", nil)\n\t}\n\tsb, err := c.client.Connect(ctx, sandboxID)\n\tif err != nil {\n\t\treturn nil, normalizeCubeError(\"Connect\", err)","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/sandbox/cube_remote_client.go#L496-L532","documentation":"After the Cube SDK's Create call succeeds, the client validates the returned sandbox object actually carries a SandboxID. An empty ID from a successful create means the SDK returned a nil/zero-value sandbox, which would produce an unusable handle — so it is rejected with a normalized api error.","triggerScenarios":"Calling Create on the cube remote client when the upstream Cube API responds 2xx but with a nil sandbox body or an empty sandboxID field — e.g. API version mismatch, partially degraded service, or mocked SDK returning &Sandbox{} in tests.","commonSituations":"Cube service deployment returning empty payloads on create; proxy/gateway stripping response bodies; unit-test fakes that forget to set SandboxID; SDK upgrade changing response struct field names.","solutions":["Check the Cube service logs/health for a version whose create endpoint returns valid payloads; upgrade or roll back accordingly.","Verify network path (proxy/gateway) is not truncating the create response body.","If using a test fake, set SandboxID on the returned sandbox to mimic real responses.","Retry the create; if persistent, inspect the raw SDK response to see what fields the API actually returns."],"exampleFix":"// before: fake SDK in test returns empty sandbox\nreturn &Sandbox{}, nil\n// after: emulate real API payload\nreturn &Sandbox{SandboxID: \"sbx-123\", Status: \"running\"}, nil","handlingStrategy":"retry","validationCode":"// nothing pre-call validates the response, but guard post-call:\nif sb != nil && sb.SandboxID != \"\" { /* usable */ }","typeGuard":"func sandboxUsable(sb *Sandbox) bool {\n    return sb != nil && sb.SandboxID != \"\"\n}","tryCatchPattern":"sb, err := client.Create(ctx, opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"empty sandboxID\") {\n        // transient upstream issue; retry with backoff, then alert\n        return retryWithBackoff(ctx, func() error { _, err := client.Create(ctx, opts); return err })\n    }\n    return err\n}","preventionTips":["Keep the Cube SDK and service versions compatible.","Set SandboxID in test fakes to mirror real payloads.","Monitor Cube service health; alert on 2xx responses with empty bodies.","Check proxies/gateways for response-body rewrites."],"tags":["sandbox","api-response","invariant-violation"],"backgroundTag":"empty-response-payload","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}