nanocoai/nanoclaw · error · Error

${flag} must be one of: ${def.enum.join(', ')}

Error message

${flag} must be one of: ${def.enum.join(', ')}

What it means

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.

Source

Thrown at src/cli/crud.ts:449

        else throw new Error(`${flag} must be true or false, got "${v}"`);
        break;
      }
      case 'json': {
        if (typeof v === 'string') {
          try {
            out[def.name] = JSON.parse(v);
          } catch (err) {
            throw new Error(`${flag} must be valid JSON`, { cause: err });
          }
        }
        break;
      }
      case 'string':
        out[def.name] = String(v);
        break;
    }
    if (def.enum && !def.enum.includes(String(out[def.name]))) {
      throw new Error(`${flag} must be one of: ${def.enum.join(', ')}`);
    }
  }
  return out;
}

// ---------------------------------------------------------------------------
// registerResource
// ---------------------------------------------------------------------------

export function registerResource(def: ResourceDef): void {
  resources.set(def.plural, def);

  if (def.operations.list) {
    register({
      name: `${def.plural}-list`,
      action: `${def.plural}.list`,
      description: `List all ${def.plural}.`,
      access: def.operations.list,

View on GitHub (pinned to 294ef2aee8)

Solutions

  1. Copy one of the values listed verbatim in the error message (they are authoritative)
  2. Run `ncl <resource> help` to confirm the full accepted set for your version
  3. Check for casing — matching is exact and case-sensitive
  4. If a value you expect is missing, update the checkout — it may be a newer enum member

Example fix

# before
ncl groups config update --id g1 --provider Claude
# Error: --provider must be one of: claude, opencode, codex

# after
ncl groups config update --id g1 --provider claude
Defensive patterns

Strategy: validation

Validate before calling

if (allowedValues.length && !allowedValues.includes(String(v))) throw new Error(`--${name} must be one of ${allowedValues.join(', ')}`);

Type guard

function isEnumValue<T extends string>(v: unknown, allowed: readonly T[]): v is T {
  return typeof v === 'string' && (allowed as readonly string[]).includes(v);
}

Try / catch

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; }

Prevention

When it happens

Trigger: 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`.

Common situations: Version drift after /update-nanoclaw adds or renames enum members; guessing values without reading help; case-sensitive values documented elsewhere in different casing.

Related errors


AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28). Data as JSON: /api/errors/7175a5c9877ba6fc. Report an issue: GitHub.