{"record":{"id":"253fa35e3504c5e1","repo":"Tencent/WeKnora","slug":"e2bapikey-is-required-for-the-e2b-backend","errorCode":null,"errorMessage":"E2BAPIKey is required for the E2B backend","messagePattern":"E2BAPIKey is required for the E2B backend","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/sandbox/e2b_remote_client.go","lineNumber":77,"sourceCode":"func NewE2BRemoteClientWithPool(\n\tcfg *Config,\n\tpool *SandboxGatewayTransportPool,\n) (*E2BRemoteClient, error) {\n\tif pool == nil {\n\t\treturn newE2BRemoteClient(cfg, nil)\n\t}\n\treturn newE2BRemoteClient(cfg, pool.RoundTripperFor(cfg))\n}\n\nfunc newE2BRemoteClient(\n\tcfg *Config,\n\ttransport http.RoundTripper,\n) (*E2BRemoteClient, error) {\n\tif cfg == nil {\n\t\treturn nil, errors.New(\"e2b remote client config is required\")\n\t}\n\tif strings.TrimSpace(cfg.E2BAPIKey) == \"\" {\n\t\treturn nil, errors.New(\"E2BAPIKey is required for the E2B backend\")\n\t}\n\ttimeout := cfg.E2BHTTPTimeout\n\tif timeout <= 0 {\n\t\ttimeout = DefaultE2BHTTPTimeout\n\t}\n\t// Every E2B client speaks to envd through the compatibility shim, whether\n\t// or not a gateway is configured: the two details it rewrites belong to the\n\t// envd protocol itself, not to any one deployment. See envd_compat_transport.go.\n\thttpClient := &http.Client{\n\t\tTimeout:   timeout,\n\t\tTransport: NewEnvdCompatTransport(transport, DefaultSandboxExecUser),\n\t}\n\tclient, err := e2b.NewClient(e2b.ClientConfig{\n\t\tAPIKey:        cfg.E2BAPIKey,\n\t\tAPIBaseURL:    strings.TrimSpace(cfg.E2BAPIURL),\n\t\tSandboxDomain: strings.TrimSpace(cfg.E2BSandboxDomain),\n\t\tHTTPClient:    httpClient,\n\t})","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/sandbox/e2b_remote_client.go#L59-L95","documentation":"The E2B backend authenticates every envd request with cfg.E2BAPIKey, so newE2BRemoteClient rejects construction when the key is missing or whitespace-only. Unlike a network auth failure, this fires locally at client construction so the misconfiguration is caught before any request is sent.","triggerScenarios":"Calling NewE2BRemoteClientWithTransport or NewE2BRemoteClientWithPool with a Config whose E2BAPIKey is \"\" or only whitespace (TrimSpace is applied).","commonSituations":"E2B_API_KEY environment variable not set in CI or a fresh checkout; secret manager injection failed; key set under a different env var name after a rename; expired credentials removed from config.","solutions":["Set cfg.E2BAPIKey (e.g. from the E2B_API_KEY environment variable) before constructing the client","Verify the secret is actually present in the environment/secret manager at runtime (echo presence, not value)","Check for key-name typos or whitespace-only values in config files"],"exampleFix":"// before\ncfg := &sandbox.Config{} // E2BAPIKey empty\n// after\nkey := os.Getenv(\"E2B_API_KEY\")\nif key == \"\" {\n    return nil, errors.New(\"E2B_API_KEY not set\")\n}\ncfg := &sandbox.Config{E2BAPIKey: key}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(cfg.E2BAPIKey) == \"\" {\n    return errors.New(\"E2B_API_KEY must be set before constructing the E2B client\")\n}","typeGuard":"func hasE2BAPIKey(cfg *sandbox.Config) bool {\n    return cfg != nil && strings.TrimSpace(cfg.E2BAPIKey) != \"\"\n}","tryCatchPattern":null,"preventionTips":["Fail at process startup if E2B_API_KEY is absent whenever the E2B backend is selected","Never hand-copy keys into config files — inject via environment or secret manager","Check key presence (not value) in CI before running sandbox-dependent jobs"],"tags":["go","sandbox","e2b","config","api-key","credentials"],"backgroundTag":"missing-api-key","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}