Skip to content

Commit 2c42ae9

Browse files
tomassrnkaclaude
andcommitted
fix(cli): resolve team ID from env var, avoid config mismatch
When E2B_API_KEY is set via environment variable, the CLI was still reading teamId from ~/.e2b/config.json, causing "Team ID param mismatch" errors when the config file belonged to a different team. Add E2B_TEAM_ID env var support and a resolveTeamId() helper with proper precedence: CLI --team flag > E2B_TEAM_ID env var > config file (config file team ID is only used when E2B_API_KEY env var is NOT set). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8efc53c commit 2c42ae9

File tree

5 files changed

+37
-22
lines changed

5 files changed

+37
-22
lines changed

packages/cli/src/api.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { asBold, asPrimary } from './utils/format'
66

77
export let apiKey = process.env.E2B_API_KEY
88
export let accessToken = process.env.E2B_ACCESS_TOKEN
9+
export const teamId = process.env.E2B_TEAM_ID
910

1011
const authErrorBox = (keyName: string) => {
1112
let link
@@ -82,6 +83,28 @@ export function ensureAccessToken() {
8283
}
8384
}
8485

86+
/**
87+
* Resolve team ID with proper precedence:
88+
* 1. CLI --team flag
89+
* 2. E2B_TEAM_ID env var
90+
* 3. Local e2b.toml team_id (if provided)
91+
* 4. ~/.e2b/config.json teamId (only if E2B_API_KEY env var is NOT set,
92+
* to avoid mismatch between env var API key and config file team ID)
93+
*/
94+
export function resolveTeamId(
95+
cliTeamId?: string,
96+
localConfigTeamId?: string
97+
): string | undefined {
98+
if (cliTeamId) return cliTeamId
99+
if (teamId) return teamId
100+
if (localConfigTeamId) return localConfigTeamId
101+
if (!process.env.E2B_API_KEY) {
102+
const config = getUserConfig()
103+
return config?.teamId
104+
}
105+
return undefined
106+
}
107+
85108
const userConfig = getUserConfig()
86109

87110
export const connectionConfig = new e2b.ConnectionConfig({

packages/cli/src/commands/template/build.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ import * as commander from 'commander'
55
import * as e2b from 'e2b'
66
import * as fs from 'fs'
77
import * as path from 'path'
8-
import { client, connectionConfig, ensureAccessToken } from 'src/api'
8+
import {
9+
client,
10+
connectionConfig,
11+
ensureAccessToken,
12+
resolveTeamId,
13+
} from 'src/api'
914
import { configName, getConfigPath, loadConfig, saveConfig } from 'src/config'
1015
import {
1116
defaultDockerfileName,
@@ -288,13 +293,9 @@ Migration guide: ${asPrimary('https://e2b.dev/docs/template/migration-v2')}`
288293
readyCmd = opts.readyCmd || config.ready_cmd
289294
cpuCount = opts.cpuCount || config.cpu_count
290295
memoryMB = opts.memoryMb || config.memory_mb
291-
teamID = opts.team || config.team_id
292296
}
293297

294-
const userConfig = getUserConfig()
295-
if (userConfig) {
296-
teamID = teamID || userConfig.teamId
297-
}
298+
teamID = resolveTeamId(opts.team, config?.team_id)
298299

299300
if (config && templateID && config.template_id !== templateID) {
300301
// error: you can't specify different ID than the one in config
@@ -444,6 +445,7 @@ Migration guide: ${asPrimary('https://e2b.dev/docs/template/migration-v2')}`
444445
cwd: root,
445446
})
446447
} catch (err: any) {
448+
const userConfig = getUserConfig()
447449
await buildWithProxy(
448450
userConfig,
449451
connectionConfig,

packages/cli/src/commands/template/delete.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ import { getRoot } from 'src/utils/filesystem'
2626
import { listSandboxTemplates } from './list'
2727
import { getPromptTemplates } from 'src/utils/templatePrompt'
2828
import { confirm } from 'src/utils/confirm'
29-
import { client } from 'src/api'
29+
import { client, resolveTeamId } from 'src/api'
3030
import { handleE2BRequestError } from '../../utils/errors'
31-
import { getUserConfig } from 'src/user'
3231

3332
async function deleteTemplate(templateID: string) {
3433
const res = await client.api.DELETE('/templates/{templateID}', {
@@ -84,10 +83,7 @@ export const deleteCommand = new commander.Command('delete')
8483
template_id: template,
8584
})
8685
} else if (opts.select) {
87-
const userConfig = getUserConfig()
88-
if (userConfig) {
89-
teamId = teamId || userConfig.teamId
90-
}
86+
teamId = resolveTeamId(teamId)
9187

9288
const allTemplates = await listSandboxTemplates({
9389
teamID: teamId,

packages/cli/src/commands/template/list.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import * as e2b from 'e2b'
44

55
import { listAliases } from '../../utils/format'
66
import { sortTemplatesAliases } from 'src/utils/templateSort'
7-
import { client, ensureAccessToken } from 'src/api'
7+
import { client, ensureAccessToken, resolveTeamId } from 'src/api'
88
import { teamOption } from '../../options'
99
import { handleE2BRequestError } from '../../utils/errors'
10-
import { getUserConfig } from '../../user'
1110

1211
export const listCommand = new commander.Command('list')
1312
.description('list sandbox templates')
@@ -17,12 +16,11 @@ export const listCommand = new commander.Command('list')
1716
.action(async (opts: { team: string; format: string }) => {
1817
try {
1918
const format = opts.format || 'pretty'
20-
const userConfig = getUserConfig()
2119
ensureAccessToken()
2220
process.stdout.write('\n')
2321

2422
const templates = await listSandboxTemplates({
25-
teamID: opts.team || userConfig?.teamId,
23+
teamID: resolveTeamId(opts.team),
2624
})
2725

2826
for (const template of templates) {

packages/cli/src/commands/template/publish.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ import { getRoot } from 'src/utils/filesystem'
2020
import { listSandboxTemplates } from './list'
2121
import { getPromptTemplates } from 'src/utils/templatePrompt'
2222
import { confirm } from 'src/utils/confirm'
23-
import { client } from 'src/api'
23+
import { client, resolveTeamId } from 'src/api'
2424
import { handleE2BRequestError } from '../../utils/errors'
25-
import { getUserConfig } from 'src/user'
2625

2726
async function publishTemplate(templateID: string, publish: boolean) {
2827
const res = await client.api.PATCH('/v2/templates/{templateID}', {
@@ -69,10 +68,7 @@ async function templateAction(
6968
template_id: template,
7069
})
7170
} else if (opts.select) {
72-
const userConfig = getUserConfig()
73-
if (userConfig) {
74-
teamId = teamId || userConfig.teamId
75-
}
71+
teamId = resolveTeamId(teamId)
7672

7773
const allTemplates = await listSandboxTemplates({
7874
teamID: teamId,

0 commit comments

Comments
 (0)