{"record":{"id":"7175a5c9877ba6fc","repo":"nanocoai/nanoclaw","slug":"flag-must-be-one-of-def-enum-join","errorCode":null,"errorMessage":"${flag} must be one of: ${def.enum.join(', ')}","messagePattern":"(.+?) must be one of: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/crud.ts","lineNumber":449,"sourceCode":"        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(', ')}`);\n    }\n  }\n  return out;\n}\n\n// ---------------------------------------------------------------------------\n// registerResource\n// ---------------------------------------------------------------------------\n\nexport function registerResource(def: ResourceDef): void {\n  resources.set(def.plural, def);\n\n  if (def.operations.list) {\n    register({\n      name: `${def.plural}-list`,\n      action: `${def.plural}.list`,\n      description: `List all ${def.plural}.`,\n      access: def.operations.list,","sourceCodeStart":431,"sourceCodeEnd":467,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/cli/crud.ts#L431-L467","documentation":"After type coercion, if a ColumnDef declares an `enum` array the coerced value's string form must be one of the allowed entries, otherwise validation fails listing every permitted value.","triggerScenarios":"Passing an unsupported mode: `--session-mode solo` when the enum is `dedicated|shared|agent-shared`; casing mismatches (`--provider Claude` vs `claude`); passing a value valid for a different version (new/removed enum members after an update); abbreviations like `--provider oc` for `opencode`.","commonSituations":"Version drift after /update-nanoclaw adds or renames enum members; guessing values without reading help; case-sensitive values documented elsewhere in different casing.","solutions":["Copy one of the values listed verbatim in the error message (they are authoritative)","Run `ncl <resource> help` to confirm the full accepted set for your version","Check for casing — matching is exact and case-sensitive","If a value you expect is missing, update the checkout — it may be a newer enum member"],"exampleFix":"# before\nncl groups config update --id g1 --provider Claude\n# Error: --provider must be one of: claude, opencode, codex\n\n# after\nncl groups config update --id g1 --provider claude","handlingStrategy":"validation","validationCode":"if (allowedValues.length && !allowedValues.includes(String(v))) throw new Error(`--${name} must be one of ${allowedValues.join(', ')}`);","typeGuard":"function isEnumValue<T extends string>(v: unknown, allowed: readonly T[]): v is T {\n  return typeof v === 'string' && (allowed as readonly string[]).includes(v);\n}","tryCatchPattern":"catch (e) { if (e instanceof Error && /must be one of:/.test(e.message)) { const opts = e.message.split('one of:')[1].trim().split(', '); /* pick or prompt */ } else throw e; }","preventionTips":["Read allowed values from `ncl <resource> help`, not from memory","Keep a typed union of enum values in wrapper code so mismatches fail at compile time"],"tags":["cli","argument-validation","enum","allowed-values"],"backgroundTag":"value-not-in-enum","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}