{"record":{"id":"46579440742231a7","repo":"rustfs/rustfs","slug":"resource-and-notresource-cannot-both-be-specif","errorCode":null,"errorMessage":"'Resource' and 'NotResource' cannot both be specified in the same statement","messagePattern":"'Resource' and 'NotResource' cannot both be specified in the same statement","errorType":"validation","errorClass":"policy::Error","httpStatus":null,"severity":"error","filePath":"crates/policy/src/policy.rs","lineNumber":58,"sourceCode":"#[derive(thiserror::Error, Debug)]\n#[cfg_attr(test, derive(Eq, PartialEq))]\npub enum Error {\n    #[error(\"invalid Version '{0}'\")]\n    InvalidVersion(String),\n\n    #[error(\"invalid Effect '{0}'\")]\n    InvalidEffect(String),\n\n    #[error(\"both 'Action' and 'NotAction' are empty\")]\n    NonAction,\n\n    #[error(\"'Action' and 'NotAction' cannot both be specified in the same statement\")]\n    BothActionAndNotAction,\n\n    #[error(\"'Resource' is empty\")]\n    NonResource,\n\n    #[error(\"'Resource' and 'NotResource' cannot both be specified in the same statement\")]\n    BothResourceAndNotResource,\n\n    #[error(\"invalid key name: '{0}'\")]\n    InvalidKeyName(String),\n\n    #[error(\"invalid key: '{0}'\")]\n    InvalidKey(String),\n\n    #[error(\"invalid action: '{0}'\")]\n    InvalidAction(String),\n\n    #[error(\"'Action' contains mixed action families in the same statement\")]\n    MixedActionFamilies,\n\n    #[error(\"invalid resource, type: '{0}', pattern: '{1}'\")]\n    InvalidResource(String, String),\n\n    #[error(\"KMS resources require a statement whose actions are all KMS actions\")]","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/rustfs/rustfs/blob/35af688cd9d41b4346fbe27dcf7250ba72046c1f/crates/policy/src/policy.rs#L40-L76","documentation":"Returned by Statement::is_valid (crates/policy/src/policy/statement.rs:343) when a statement lists both a non-empty Resource and a non-empty NotResource. Like Action/NotAction, the positive and negated resource selectors are mutually exclusive; a statement containing both is rejected at parse time.","triggerScenarios":"A policy statement JSON containing both \"Resource\" and \"NotResource\" keys with non-empty values in any policy upload path.","commonSituations":"Incremental policy editing where a NotResource was added to exclude a new bucket but the original Resource list was left in place; merging policies with a naive union of fields.","solutions":["Delete one of the two keys so each statement has exactly one resource selection mode","Split into two statements if both scopes genuinely need different effects","Automate a pre-flight check that flags statements containing both keys"],"exampleFix":"// before\n{ \"Effect\": \"Deny\",\n  \"Action\": \"s3:*\",\n  \"Resource\": \"arn:aws:s3:::secret/*\",\n  \"NotResource\": \"arn:aws:s3:::public/*\" }\n\n// after\n{ \"Effect\": \"Deny\",\n  \"Action\": \"s3:*\",\n  \"Resource\": \"arn:aws:s3:::secret/*\" }","handlingStrategy":"validation","validationCode":"fn not_both_resource_modes(stmt: &serde_json::Value) -> bool {\n    let has = |k: &str| stmt.get(k).map(|v| !v.is_null()).unwrap_or(false);\n    !(has(\"Resource\") && has(\"NotResource\"))\n}","typeGuard":null,"tryCatchPattern":"match statement.is_valid() {\n    Err(Error::PolicyError(IamError::BothResourceAndNotResource)) => { /* keep one mode */ }\n    Ok(()) => { /* ok */ }\n    Err(e) => return Err(e),\n}","preventionTips":["When adding NotResource exclusions, delete the original Resource key in the same edit","Lint merged policies for dual resource modes"],"tags":["policy","iam","validation","rust"],"backgroundTag":"policy-statement-validation","analyzedSha":"35af688cd9d41b4346fbe27dcf7250ba72046c1f","analyzedAt":"2026-08-20T21:57:04.799Z","contentChangedAt":"2026-08-20T21:57:04.799Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}