{"record":{"id":"af640c5420a45678","repo":"langgenius/dify","slug":"usagemissingarg-af640c","errorCode":"UsageMissingArg","errorMessage":"a workspace id is required (no TTY)","messagePattern":"a workspace id is required \\(no TTY\\)","errorType":"error_code","errorClass":"BaseError","httpStatus":null,"severity":"error","filePath":"cli/src/commands/use/workspace/use.ts","lineNumber":60,"sourceCode":"  const id = argId !== '' ? argId : await pickWorkspaceId(client, deps)\n\n  const detail = await runWithSpinner({ io: deps.io, label: `Switching to ${id}` }, () =>\n    client.switch(id),\n  )\n\n  const nextCtx = {\n    ...deps.active.ctx,\n    workspace: { id: detail.id, name: detail.name, role: detail.role },\n  }\n  deps.reg.upsert(deps.active.host, deps.active.email, nextCtx)\n  await deps.reg.save()\n  deps.io.out.write(`${cs.successIcon()} Switched to ${detail.name} (${detail.id})\\n`)\n  return deps.reg\n}\n\nasync function pickWorkspaceId(client: WorkspacesClient, deps: UseWorkspaceDeps): Promise<string> {\n  if (!deps.io.isErrTTY) {\n    throw new BaseError({\n      code: ErrorCode.UsageMissingArg,\n      message: 'a workspace id is required (no TTY)',\n      hint: \"pass the id: 'difyctl use workspace <id>'\",\n    })\n  }\n\n  const list = await runWithSpinner({ io: deps.io, label: 'Loading workspaces' }, () =>\n    client.list(),\n  )\n  const items = list.workspaces.map<Workspace>((w) => ({ id: w.id, name: w.name, role: w.role }))\n  if (items.length === 0) {\n    throw new BaseError({\n      code: ErrorCode.AccessDenied,\n      message: 'no workspaces available to switch to',\n    })\n  }\n\n  const activeId = deps.active.ctx.workspace?.id","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/cli/src/commands/use/workspace/use.ts#L42-L78","documentation":"Thrown by pickWorkspaceId when difyctl is asked to switch workspaces without an explicit id AND stderr is not a TTY. The interactive picker (selectFromList) requires a TTY on stderr; in non-interactive contexts (pipelines, CI, redirected stderr) it refuses to silently guess. The BaseError carries UsageMissingArg, which exitFor maps to exit code 2 (Usage). The hint text points at the exact invocation form.","triggerScenarios":"Invoking `difyctl use workspace` with no positional id while stderr is not a TTY. Concretely: `deps.io.isErrTTY === false` (process.stderr.isTTY falsy) at use.ts:59 AND opts.workspaceId is empty/whitespace (use.ts:41). Piping stderr (`difyctl use workspace 2>log`), running under CI runners, nohup, systemd, or in a Docker container without a pseudo-tty all make isErrTTY false.","commonSituations":"CI scripts that switch workspace before running a command; shell pipelines that redirect stderr for logging; running difyctl over ssh without tty allocation (`ssh host difyctl use workspace`); Docker `docker run` without -t; cron jobs; a user who forgot the id and expected a default.","solutions":["Pass the workspace id explicitly: `difyctl use workspace <id>` (ids come from `difyctl workspaces list`).","If you genuinely need the picker, allocate a TTY: `ssh -t`, `docker run -it`, or run in a real terminal without redirecting stderr.","In scripts, look up the id first via `difyctl workspaces list -o name` or `-o json` and pipe it into `use workspace`.","Avoid redirecting stderr (`2>` or `2>&1` to a file) when you want the interactive picker; keep stderr on the terminal."],"exampleFix":"// before (fails in CI / piped stderr)\ndifyctl use workspace\n\n// after — explicit id (script-friendly)\ndifyctl use workspace ws_abc123\n\n// or — resolve id dynamically from a known name\nID=$(difyctl workspaces list -o json | jq -r '.workspaces[] | select(.name==\"prod\") | .id')\ndifyctl use workspace \"$ID\"","handlingStrategy":"validation","validationCode":"// before invoking runUseWorkspace, ensure an id is present in non-TTY contexts\nimport { runUseWorkspace, type UseWorkspaceOptions, type UseWorkspaceDeps } from '@/commands/use/workspace/use'\nimport { BaseError } from '@/errors/base'\nimport { ErrorCode } from '@/errors/codes'\n\nfunction ensureWorkspaceIdOrTty(opts: UseWorkspaceOptions, deps: UseWorkspaceDeps): void {\n  const hasId = (opts.workspaceId ?? '').trim() !== ''\n  if (!hasId && !deps.io.isErrTTY) {\n    throw new BaseError({\n      code: ErrorCode.UsageMissingArg,\n      message: 'pass --workspace-id when stderr is not a TTY',\n      hint: 'difyctl use workspace <id>',\n    })\n  }\n}\n\n// usage\nensureWorkspaceIdOrTty(opts, deps)\nconst reg = await runUseWorkspace(opts, deps)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass an explicit workspace id in scripts/CI; treat the picker as interactive-only.","Detect TTY upstream with `process.stderr.isTTY` before calling commands that pick interactively.","Resolve ids from a deterministic source (`workspaces list -o json`) rather than relying on user input."],"tags":["cli","usage","tty","workspace","interactive"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}