{"record":{"id":"135a6070709aaf03","repo":"nanocoai/nanoclaw","slug":"flag-must-be-true-or-false-got-v","errorCode":null,"errorMessage":"${flag} must be true or false, got \"${v}\"","messagePattern":"(.+?) must be true or false, got \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/crud.ts","lineNumber":431,"sourceCode":"      if (def.required) throw new Error(`${flag} is required`);\n      if (def.default !== undefined) out[def.name] = def.default;\n      continue;\n    }\n    // The client parses a value-less `--flag` as boolean true.\n    if (v === true && def.type !== 'boolean') {\n      throw new Error(`${flag} requires a value`);\n    }\n    switch (def.type) {\n      case 'number': {\n        const n = Number(v);\n        if (Number.isNaN(n)) throw new Error(`${flag} must be a number, got \"${v}\"`);\n        out[def.name] = n;\n        break;\n      }\n      case 'boolean': {\n        if (v === true || v === 'true' || v === '1') out[def.name] = true;\n        else if (v === false || v === 'false' || v === '0') out[def.name] = false;\n        else throw new Error(`${flag} must be true or false, got \"${v}\"`);\n        break;\n      }\n      case 'json': {\n        if (typeof v === 'string') {\n          try {\n            out[def.name] = JSON.parse(v);\n          } catch (err) {\n            throw new Error(`${flag} must be valid JSON`, { cause: err });\n          }\n        }\n        break;\n      }\n      case 'string':\n        out[def.name] = String(v);\n        break;\n    }\n    if (def.enum && !def.enum.includes(String(out[def.name]))) {\n      throw new Error(`${flag} must be one of: ${def.enum.join(', ')}`);","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/cli/crud.ts#L413-L449","documentation":"A flag declared with `type: 'boolean'` only accepts true/false in the forms `true|false`, `1|0`, or the bare-boolean values. Any other string fails with the received value echoed.","triggerScenarios":"`--rebuild yes`, `--engage true-ish`, `--flag on/off`, `--flag True` (capitalized — not matched by the strict string comparison), or an arbitrary word parsed as the flag's value.","commonSituations":"Using YAML-ish `yes/no` or `on/off` conventions from other CLIs; capitalized booleans; agents writing natural-language truthiness.","solutions":["Use exactly `true` or `false` (lowercase), or `1`/`0`","For a bare toggle, pass just `--flag` with no value (parsed as boolean true)","Check the usage block for the accepted forms"],"exampleFix":"# before\nncl groups restart --id g1 --rebuild yes\n# Error: --rebuild must be true or false, got \"yes\"\n\n# after\nncl groups restart --id g1 --rebuild","handlingStrategy":"validation","validationCode":"const ok = v === true || v === false || ['true','false','1','0'].includes(String(v).toLowerCase());\nif (!ok) throw new Error('boolean flag must be true/false/1/0');","typeGuard":"function isBooleanFlagValue(v: unknown): v is boolean | 'true' | 'false' | '1' | '0' {\n  return v === true || v === false || ['true','false','1','0'].includes(v as string);\n}","tryCatchPattern":"catch (e) { if (e instanceof Error && /must be true or false/.test(e.message)) { /* map yes/no → true/false */ } else throw e; }","preventionTips":["Use lowercase true/false exactly; for toggles just pass the bare flag","Map yes/no inputs to true/false in wrapper scripts"],"tags":["cli","argument-validation","boolean","type-coercion"],"backgroundTag":"invalid-argument-type","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}