xai-org/grok-build · error
--permission-mode: invalid value: {e}
Error message
--permission-mode: invalid value: {e} What it means
In run_single_turn, the --permission-mode CLI flag string is deserialized into the permission-mode enum via serde_json::from_value; any non-enum string produces '--permission-mode: invalid value: {e}' (raised via CliAgentOverrides). It is a pure CLI input validation error, not a runtime condition.
Source
Thrown at crates/codegen/xai-grok-pager/src/headless.rs:837
);
apply_agent_flag(&options.agent, &mut agent_config);
if let Some(ref json) = options.agents_json {
agent_config.cli_agents = parse_cli_agents(json)?;
}
agent_config.cli_agent_overrides = xai_grok_shell::agent::config::CliAgentOverrides {
tools: parse_comma_list(options.cli_tools.as_deref()),
disallowed_tools: parse_comma_list(options.cli_disallowed_tools.as_deref()),
permission_rules: parse_permission_rules_strict(&options.allow_rules, &options.deny_rules)?,
max_turns: options.max_turns,
permission_mode: options
.permission_mode_flag
.as_deref()
.map(|s| {
serde_json::from_value(serde_json::Value::String(s.to_string()))
.map_err(|e| anyhow::anyhow!("--permission-mode: invalid value: {e}"))
})
.transpose()?,
};
if options.trust {
xai_grok_workspace::folder_trust::grant_folder_trust(&cwd);
}
let cancel = CancellationToken::new();
let memory_config = agent_config.memory_config.clone();
let mut pending_startup = Some(PendingStartup::new());
let timer = xai_grok_telemetry::startup::begin(crate::acp::Owner::Client);
let mut report_startup_failure = |timer: &crate::acp::StartupTimer| {
timer.emit_telemetry(
crate::acp::AgentKind::Embedded,
crate::acp::StartupOutcome::Error,
None,
false,View on GitHub (pinned to bc7f02eddd)
Solutions
- Use an exact supported value (check --help for the accepted list)
- Fix casing — the enum match is typically case-sensitive
- Upgrade/downgrade the binary so the flag matches a supported mode
- Validate the flag in the wrapper script before invoking
Example fix
// before pager --permission-mode AcceptEdits // after pager --permission-mode accept-edits
Defensive patterns
Strategy: validation
Validate before calling
const VALID_MODES: [&str; 3] = ["default", "accept-edits", "plan"];
fn valid_permission_mode(s: &str) -> bool { VALID_MODES.contains(&s) } Type guard
fn is_permission_mode(s: &str) -> bool {
matches!(s, "default" | "accept-edits" | "plan")
} Try / catch
match serde_json::from_value::<PermissionMode>(serde_json::Value::String(mode.into())) {
Ok(m) => m,
Err(e) => { eprintln!("--permission-mode: invalid value: {e}"); std::process::exit(2); }
} Prevention
- Copy flag values from --help of the exact binary version
- Quote flag values in shell scripts to avoid whitespace
- Add a wrapper that whitelists allowed modes
- Test CLI invocations in CI before production use
When it happens
Trigger: Passing --permission-mode with a value not in the enum (wrong case like 'Default' vs 'default', or a mode the binary does not support such as 'bypassPermissions' on a build without it).
Common situations: Typo or wrong casing in scripts/CI wrappers; copying flags from docs of a different version; shell quoting introducing stray whitespace.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Error: --session-id must be a valid UUID (got '{session_id}'
- {CHAT_MODE_FORK_CONFLICT}
- --header can only be used with HTTP or SSE servers.
- A URL is required for {label} servers. Usage: grok mcp add -
- Invalid URL '{url}'. Server URLs must start with http:// or
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/a7ea7c504fffc794.
Report an issue: GitHub.