{"record":{"id":"7f369a21dcd83bce","repo":"Hmbown/CodeWhale","slug":"refusing-inconsistent-permission-removal-at","errorCode":null,"errorMessage":"refusing inconsistent permission removal at {}","messagePattern":"refusing inconsistent permission removal at (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/lib.rs","lineNumber":6257,"sourceCode":"        let mut document = parse_permissions_document(path, &raw)?;\n        let rules_item = document.get_mut(\"rules\").with_context(|| {\n            format!(\n                \"permissions at {} no longer contain a rules array\",\n                quote_os_path(path)\n            )\n        })?;\n        let orphaned_header = remove_permission_rule_item(rules_item, index)?;\n        if let Some(header) = orphaned_header {\n            let trailing = format!(\n                \"{header}{}\",\n                document.trailing().as_str().unwrap_or_default()\n            );\n            document.set_trailing(trailing);\n        }\n        let body = document.to_string();\n        let persisted = parse_generated_permissions(path, &body)?;\n        if persisted.rules.len() + 1 != permissions.rules.len() {\n            bail!(\n                \"refusing inconsistent permission removal at {}\",\n                quote_os_path(path)\n            );\n        }\n        write_permissions_atomic(path, body.as_bytes())?;\n        Ok(rule)\n    })\n}\n\nfn load_sibling_permissions(config_path: &Path) -> Result<PermissionsToml> {\n    let permissions_path = checked_permissions_path_for_config_path(config_path)?;\n    let (_, _, permissions) = read_permissions_state(&permissions_path)?;\n    Ok(permissions)\n}\n\nfn read_permissions_state(path: &Path) -> Result<(bool, String, PermissionsToml)> {\n    let file_exists = checked_path_exists(path)?;\n    let raw = if file_exists {","sourceCodeStart":6239,"sourceCodeEnd":6275,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/config/src/lib.rs#L6239-L6275","documentation":"After remove_permission_rule edits the TOML document, it re-parses the generated body and asserts the result contains exactly one fewer rule than before. If the re-parse or count check fails, the library refuses to persist the edit, protecting permissions.toml from a corrupting or surprising write.","triggerScenarios":"remove_permission_rule where parse_generated_permissions of the serialized document yields a rule count that is not exactly (original - 1), e.g. the edit removed zero or multiple rules.","commonSituations":"A permissions.toml with unusual structure (rules declared in a shape the editor mishandles, duplicate `rules` keys, inline-table arrays with embedded header comments) causing the round-trip to drop or merge rules; a bug in the removal path after manual hand-editing of the file.","solutions":["Inspect permissions.toml for unusual structure (multiple `rules` keys, odd comments between [[rules]] tables) and normalize it to a plain array of tables","Re-run load_permissions_snapshot and remove the rule again from a fresh snapshot","Restore permissions.toml from backup or regenerate it, then remove the rule via the API"],"exampleFix":"// before (hand-edited, ambiguous file)\nrules = []\n[[rules]]\ntool = \"bash\"\n\n// after (normalized)\n[[rules]]\ntool = \"bash\"","handlingStrategy":"validation","validationCode":"// pre-parse permissions.toml yourself; reject ambiguous structure before calling the API\nlet raw = std::fs::read_to_string(&path)?;\nlet parsed: PermissionsToml = toml::from_str(&raw)?; // fails on non-standard shapes","typeGuard":"fn rules_is_array(doc: &toml_edit::DocumentMut) -> bool {\n    matches!(doc.get(\"rules\"), Some(toml_edit::Item::ArrayOfTables(_))\n        | Some(toml_edit::Item::Value(v)) if v.is_array())\n}","tryCatchPattern":"match remove_permission_rule(path, index, &token) {\n    Err(e) if e.to_string().contains(\"refusing inconsistent permission removal\") => {\n        eprintln!(\"normalize permissions.toml structure, reload snapshot, retry\");\n    }\n    other => other?,\n}","preventionTips":["Keep permissions.toml as a plain [[rules]] array of tables; avoid hand-crafted comment headers and duplicate keys","Round-trip the file through the library's own load/save rather than external formatters","Back up permissions.toml before scripted bulk edits"],"tags":["config","permissions","atomic-write","toml"],"backgroundTag":"file-write-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}