{"record":{"id":"57c7dfc2c9a51fe2","repo":"langgenius/dify","slug":"usage-missing-arg-57c7df","errorCode":"usage_missing_arg","errorMessage":"member id is required","messagePattern":"member id is required","errorType":"error_code","errorClass":"BaseError","httpStatus":null,"severity":"error","filePath":"cli/src/commands/delete/member/run.ts","lineNumber":39,"sourceCode":"export type DeleteMemberDeps = {\n  readonly active: ActiveContext\n  readonly http: HttpClient\n  readonly io?: IOStreams\n  readonly envLookup?: (k: string) => string | undefined\n  readonly membersFactory?: (http: HttpClient) => MembersClient\n}\n\nexport type DeleteMemberResult = {\n  readonly data: DeleteMemberOutput\n  readonly workspaceId: string\n}\n\nexport async function runDeleteMember(\n  opts: DeleteMemberOptions,\n  deps: DeleteMemberDeps,\n): Promise<DeleteMemberResult> {\n  if (opts.memberId === undefined || opts.memberId === '') {\n    throw new BaseError({\n      code: ErrorCode.UsageMissingArg,\n      message: 'member id is required',\n      hint: 'pass it positionally: difyctl delete member <member-id>',\n    })\n  }\n\n  const env = deps.envLookup ?? ((k: string) => process.env[k])\n  const factory = deps.membersFactory ?? ((h: HttpClient) => new MembersClient(h))\n  const io = deps.io ?? nullStreams()\n  const cs = colorScheme(colorEnabled(io.isErrTTY))\n\n  const wsId = resolveWorkspaceId({\n    flag: opts.workspace,\n    env: env('DIFY_WORKSPACE_ID'),\n    active: deps.active,\n  })\n\n  if (!opts.yes && io.isErrTTY) {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/cli/src/commands/delete/member/run.ts#L21-L57","documentation":"Raised by RagPipelineVariableApi.get when the variable exists (get_variable returned a row) but its variable.app_id does not equal pipeline.id — i.e. the variable belongs to a different pipeline. The same 'variable not found' message is deliberately reused to avoid leaking the existence of a variable owned by another pipeline (an authorization-vs-existence blending). Maps to HTTP 404.","triggerScenarios":"GET /console/api/rag/pipelines/{pipeline_id}/workflows/draft/variables/{variable_id} where variable_id exists but is owned by a different pipeline. Happens when a variable_id from pipeline A is sent under the URL of pipeline B — e.g. copy-paste across pipelines, or a client that reuses a variable_id after the user switched pipelines.","commonSituations":"User switched pipelines in the UI but the deep link still carries a variable_id from the previous pipeline; automation script hardcoded a variable_id while targeting a different pipeline; pipeline was duplicated and the client reused the source pipeline's variable_id against the copy.","solutions":["Ensure the variable_id was obtained from the same pipeline_id (list variables under the target pipeline first).","When switching pipelines in the UI, clear cached variable_ids.","Treat the 404 identically to a missing variable: re-list variables under the current pipeline."],"exampleFix":"// before — variableId belongs to pipeline A, called against pipeline B\nawait get(`/rag/pipelines/${pipelineB}/workflows/draft/variables/${varFromA}`);\n// after\nconst { items } = await get(`/rag/pipelines/${pipelineB}/workflows/draft/variables`).then(r => r.json());\nconst local = items.find(x => x.id === varId);\nif (!local) { notify('Variable not in this pipeline'); return; }","handlingStrategy":"validation","validationCode":"async function variableBelongsToPipeline(client, pipelineId: string, variableId: string): Promise<boolean> {\n  const r = await client.get(`/console/api/rag/pipelines/${pipelineId}/workflows/draft/variables`);\n  const { items = [] } = await r.json();\n  return items.some(v => v.id === variableId);\n}\nif (!(await variableBelongsToPipeline(client, pipelineId, variableId))) {\n  throw new Error(`variable ${variableId} not in pipeline ${pipelineId}`);\n}","typeGuard":"function isVariableInPipeline(variable: { app_id?: string }, pipelineId: string): boolean {\n  return variable?.app_id === pipelineId;\n}","tryCatchPattern":"try {\n  return await client.get(`/rag/pipelines/${pipelineId}/workflows/draft/variables/${variableId}`);\n} catch (e) {\n  if (e.response?.status === 404) {\n    // could be missing OR owned by another pipeline — re-list under this pipeline\n    await reloadVariables(pipelineId);\n    return null;\n  }\n  throw e;\n}","preventionTips":["Always obtain variable_id from the same pipeline's variable list.","Clear cached variable_ids when switching pipelines.","Recognize that the same 404 message covers missing and cross-pipeline cases by design."],"tags":["rag-pipeline","workflow","variables","not-found","authorization","info-leak-prevention","rest-api","console"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}