langgenius/dify · error · Error

expected boolean, got ${JSON.stringify(raw)}

Error message

expected boolean, got ${JSON.stringify(raw)}

What it means

A bare Error from the 'boolean' case of coerceFlagValue (flags.ts:100). Only the four literal strings are accepted: 'true'/'1' → true, 'false'/'0' → false. Anything else (yes, no, on, off, True, t, enable) throws. Like the integer case it's a plain Error, not a BaseError, so exit-code routing is lost. Inline assignment via `--flag=value` and the explicit-next-token form both pass through coerceFlagValue, so both are subject to this restriction.

Source

Thrown at cli/src/framework/flags.ts:100

export const Args = {
  string: stringArg,
}

function coerceFlagValue(raw: string, def: FlagDefinition): string | boolean | number {
  switch (def.type) {
    case 'integer': {
      const n = Number(raw)
      if (Number.isNaN(n)) throw new Error(`expected integer, got ${JSON.stringify(raw)}`)

      return n
    }
    case 'boolean': {
      if (raw === 'true' || raw === '1') return true

      if (raw === 'false' || raw === '0') return false

      throw new Error(`expected boolean, got ${JSON.stringify(raw)}`)
    }
    default:
      return raw
  }
}

function accumulateFlagValue(
  flags: ParsedFlags,
  name: string,
  value: string | boolean | number,
  def: FlagDefinition,
): void {
  if (def.multiple === true) {
    const existing = flags[name]
    flags[name] = Array.isArray(existing) ? [...existing, String(value)] : [String(value)]
  } else {
    flags[name] = value
  }

View on GitHub (pinned to ef8544b173)

Solutions

  1. Use one of the four accepted literals: `--verbose=true`, `--verbose=1`, `--verbose=false`, `--verbose=0`.
  2. For bare boolean flags just write `--verbose` (no value) — parseArgv treats it as true (flags.ts:212).
  3. Normalize values in your wrapper script: `[[ "$V" =~ ^(true|1)$ ]] && V=true || V=false`.
  4. If maintaining difyctl: widen the accepted set and/or lowercase before compare, and wrap as BaseError(UsageInvalidFlag) for a proper exit 2.

Example fix

// before
difyctl logs --follow=yes
difyctl apps list --verbose=True

// after
difyctl logs --follow
difyctl apps list --verbose=true   // or just --verbose
Defensive patterns

Strategy: validation

Validate before calling

// normalize arbitrary truthy strings to the four literals difyctl accepts
function toCliBoolean(raw: string): 'true' | 'false' | '1' | '0' {
  const v = raw.trim().toLowerCase()
  if (v === 'true' || v === '1' || v === 'yes' || v === 'on') return 'true'
  if (v === 'false' || v === '0' || v === 'no' || v === 'off') return 'false'
  throw new Error(`cannot normalize ${JSON.stringify(raw)} to a cli boolean`)
}

Type guard

function isAcceptedBoolean(raw: string): boolean {
  return ['true', '1', 'false', '0'].includes(raw)
}

Prevention

When it happens

Trigger: `--verbose=yes`, `--color=on`, `--no-cache=false-but-quoted`, `--follow true` works but `--follow True` (capital T) does NOT — the check is case-sensitive. Also `--flag=` (empty) throws, and any whitespace-bearing value.

Common situations: Coming from tools that accept on/off or yes/no (systemd, git config, env-style configs); case mismatch from copy-paste; YAML/JSON-derived boolean capitalization (true vs True vs TRUE); locale-influenced typing.

Related errors


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