{"record":{"id":"4279f3058172150b","repo":"langgenius/dify","slug":"expected-boolean-got-json-stringify-raw","errorCode":null,"errorMessage":"expected boolean, got ${JSON.stringify(raw)}","messagePattern":"expected boolean, got (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/framework/flags.ts","lineNumber":100,"sourceCode":"\nexport const Args = {\n  string: stringArg,\n}\n\nfunction coerceFlagValue(raw: string, def: FlagDefinition): string | boolean | number {\n  switch (def.type) {\n    case 'integer': {\n      const n = Number(raw)\n      if (Number.isNaN(n)) throw new Error(`expected integer, got ${JSON.stringify(raw)}`)\n\n      return n\n    }\n    case 'boolean': {\n      if (raw === 'true' || raw === '1') return true\n\n      if (raw === 'false' || raw === '0') return false\n\n      throw new Error(`expected boolean, got ${JSON.stringify(raw)}`)\n    }\n    default:\n      return raw\n  }\n}\n\nfunction accumulateFlagValue(\n  flags: ParsedFlags,\n  name: string,\n  value: string | boolean | number,\n  def: FlagDefinition,\n): void {\n  if (def.multiple === true) {\n    const existing = flags[name]\n    flags[name] = Array.isArray(existing) ? [...existing, String(value)] : [String(value)]\n  } else {\n    flags[name] = value\n  }","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/cli/src/framework/flags.ts#L82-L118","documentation":"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.","triggerScenarios":"`--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.","commonSituations":"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.","solutions":["Use one of the four accepted literals: `--verbose=true`, `--verbose=1`, `--verbose=false`, `--verbose=0`.","For bare boolean flags just write `--verbose` (no value) — parseArgv treats it as true (flags.ts:212).","Normalize values in your wrapper script: `[[ \"$V\" =~ ^(true|1)$ ]] && V=true || V=false`.","If maintaining difyctl: widen the accepted set and/or lowercase before compare, and wrap as BaseError(UsageInvalidFlag) for a proper exit 2."],"exampleFix":"// before\ndifyctl logs --follow=yes\ndifyctl apps list --verbose=True\n\n// after\ndifyctl logs --follow\ndifyctl apps list --verbose=true   // or just --verbose","handlingStrategy":"validation","validationCode":"// normalize arbitrary truthy strings to the four literals difyctl accepts\nfunction toCliBoolean(raw: string): 'true' | 'false' | '1' | '0' {\n  const v = raw.trim().toLowerCase()\n  if (v === 'true' || v === '1' || v === 'yes' || v === 'on') return 'true'\n  if (v === 'false' || v === '0' || v === 'no' || v === 'off') return 'false'\n  throw new Error(`cannot normalize ${JSON.stringify(raw)} to a cli boolean`)\n}","typeGuard":"function isAcceptedBoolean(raw: string): boolean {\n  return ['true', '1', 'false', '0'].includes(raw)\n}","tryCatchPattern":null,"preventionTips":["Prefer bare boolean flags (`--verbose`) over `--verbose=value`.","When scripting from config formats that use yes/no/on/off, normalize before invoking difyctl.","Remember the check is case-sensitive: only lowercase true/false/1/0."],"tags":["cli","flags","parsing","boolean","validation"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}