langgenius/dify · error · BaseError

UsageInvalidFlag

UsageInvalidFlag

Error message

invalid selection: ${line.trim()}

What it means

BaseError(UsageInvalidFlag, exit 2) from pickNumbered (select.ts:142), the non-TTY fallback picker. After printing a numbered menu it reads one line from stdin, trims, calls Number() on it, and indexes items[n-1]. If Number() returns NaN (non-numeric) or the index is out of range, chosen is undefined and the error throws echoing the offending input. Note Number('') === 0 and Number('1.5') is truthy but items[0.5] is undefined — so empty input and decimals also fail.

Source

Thrown at cli/src/sys/io/select.ts:142

function cancelled(): BaseError {
  return new BaseError({ code: ErrorCode.UsageMissingArg, message: 'selection cancelled' })
}

async function pickNumbered<T>(opts: SelectOptions<T>): Promise<T> {
  opts.io.err.write(`${opts.header}\n`)
  opts.items.forEach((item, idx) => {
    opts.io.err.write(`  ${idx + 1}) ${opts.render(item)}\n`)
  })
  opts.io.err.write('Enter number: ')

  const rl = readline.createInterface({ input: opts.io.in, output: opts.io.err, terminal: false })
  try {
    const line: string = await new Promise((resolve) => rl.once('line', resolve))
    const n = Number(line.trim())
    const chosen = Number.isInteger(n) ? opts.items[n - 1] : undefined
    if (chosen === undefined)
      throw new BaseError({
        code: ErrorCode.UsageInvalidFlag,
        message: `invalid selection: ${line.trim()}`,
      })
    return chosen
  } finally {
    rl.close()
  }
}

View on GitHub (pinned to ef8544b173)

Solutions

  1. Enter a single integer in the displayed range (1..N).
  2. When scripting, pipe exactly the numeric index: `echo 2 | difyctl ...`, or better, avoid the picker by passing the id directly.
  3. If the input source may be empty, guard it upstream and pass an explicit id instead of relying on the numbered prompt.
  4. For maintainers: reject empty/whitespace and non-integer input earlier with a clearer message; consider re-prompting in interactive non-TTY contexts.

Example fix

# before — non-numeric or out-of-range piped input
echo abc | difyctl use workspace
echo 99 | difyctl use workspace   # only 2 workspaces listed

# after — valid index in range, or skip the picker
echo 2 | difyctl use workspace
difyctl use workspace ws_abc123   # preferred: explicit id
Defensive patterns

Strategy: validation

Validate before calling

// validate piped/typed input for the numbered picker
function parsePickerIndex(line: string, count: number): number {
  const n = Number(line.trim())
  if (!Number.isInteger(n) || n < 1 || n > count) {
    throw new Error(`expected an integer 1..${count}, got ${JSON.stringify(line)}`)
  }
  return n
}

Type guard

function isValidPickerIndex(line: string, count: number): boolean {
  const n = Number(line.trim())
  return Number.isInteger(n) && n >= 1 && n <= count
}

Prevention

When it happens

Trigger: Non-TTY mode (isErrTTY false) where the user types anything other than a positive integer in range: empty line, 'abc', '0', '99' (beyond list), '1.5', '1,' (trailing comma), or piping a wrong value (`echo name | difyctl ...`).

Common situations: Scripting the picker by piping a value but using the wrong column; EOF on stdin (closed pipe) resolves the line promise with undefined → `undefined.trim()` would throw before this — but a blank line yields '' which Number() turns to 0 → items[-1] undefined → this error; copy-paste included extra text; user pressed Enter without choosing.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/e58bfa7a2740912f. Report an issue: GitHub.