Hmbown/CodeWhale · error
permission rule action does not match requested
Error message
permission rule action does not match requested {:?} persistence What it means
When appending permission rules under a requested persistence mode, every rule in the batch must already carry the action (`Allow`/`Ask`/etc.) matching that mode. A mixed or mismatched batch indicates a caller bug, so the whole write is aborted rather than persisting rules under the wrong action.
Solutions
- Filter the batch to only rules whose `action` equals the requested action before appending
- Set each rule's `action` to the requested action when constructing the batch
- Split the batch into separate calls per action/persistence kind
Example fix
// before
rules.push(PermissionRule { action: PermissionAction::Ask, .. });
append_permission_rules(&rules, PermissionAction::Allow);
// after
rules.push(PermissionRule { action: PermissionAction::Allow, .. });
append_permission_rules(&rules, PermissionAction::Allow); Defensive patterns
Strategy: validation
Validate before calling
fn actions_match(rules: &[PermissionRule], expected: PermissionAction) -> bool {
rules.iter().all(|r| r.action == expected)
} Try / catch
match config.append_permission_rules(&rules, expected_action) {
Err(e) if e.to_string().contains("does not match requested") => {
// split batch by action or rewrite actions, then retry
}
result => result?,
} Prevention
- Construct each batch from a single source so all actions agree
- Assert batch action homogeneity before calling persistence APIs
- Filter `rules.retain(|r| r.action == expected)` before appending
When it happens
Trigger: Calling `append_permission_rules` (or the allow/ask wrappers around it) with a batch where at least one rule's `action` field differs from the `expected_action` parameter for the requested persistence kind.
Common situations: Batching rules collected from different sources (some Allow, some Ask) into one persistence call; copying a rule from an Ask list into an Allow append; a refactor changing the expected action without updating rule construction.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- agent profile tools.posture= would widen permissions; use…
- external credential access is disabled for
- failed to parse permissions at
- Failed to read MCP config
- parallel(): max 1000 items per call
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/5961c7908d82a01b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/lib.rs:5368
&& codewhale_execpolicy::normalize_workspace_relative_path(path, &workspace)
.is_none_or(|path| path.is_empty())
{
bail!("persistent path allow rules must stay within the workspace");
}
}
self.append_permission_rules(rules, PermissionAction::Allow)
}
fn append_permission_rules(
&mut self,
rules: &[ToolAskRule],
expected_action: PermissionAction,
) -> Result<usize> {
if rules.is_empty() {
return Ok(0);
}
if rules.iter().any(|rule| rule.action != expected_action) {
bail!(
"permission rule action does not match requested {:?} persistence",
expected_action
);
}
let path = checked_permissions_path_for_config_path(&self.path)?;
let (added, persisted) = config_document::with_config_write_lock(&path, |path| {
let (_, raw, mut permissions) = read_permissions_state(path)?;
let mut document = parse_permissions_document(path, &raw)?;
if !document.contains_key("rules") {
document["rules"] = toml_edit::Item::ArrayOfTables(toml_edit::ArrayOfTables::new());
}
let rules_item = document
.get_mut("rules")
.expect("rules entry was inserted above");
let mut added = 0;View on GitHub (pinned to 73e0f67d83)