{"record":{"id":"0676b890bdc2af14","repo":"linera-io/linera-protocol","slug":"all-operations-on-this-chain-must-be-from-one-of-t","errorCode":null,"errorMessage":"All operations on this chain must be from one of the following applications: {0:?}","messagePattern":"All operations on this chain must be from one of the following applications: (.+?)","errorType":"validation","errorClass":"ChainError","httpStatus":null,"severity":"error","filePath":"linera-chain/src/chain.rs","lineNumber":1602,"sourceCode":"    ))]\n    fn check_app_permissions(\n        app_permissions: &ApplicationPermissions,\n        block: &ProposedBlock,\n    ) -> Result<(), ChainError> {\n        let mut mandatory = app_permissions\n            .mandatory_applications\n            .iter()\n            .copied()\n            .collect::<HashSet<ApplicationId>>();\n        for transaction in &block.transactions {\n            match transaction {\n                Transaction::ExecuteOperation(operation)\n                    if operation.is_exempt_from_permissions() =>\n                {\n                    mandatory.clear()\n                }\n                Transaction::ExecuteOperation(operation) => {\n                    ensure!(\n                        app_permissions.can_execute_operations(&operation.application_id()),\n                        ChainError::AuthorizedApplications(\n                            app_permissions.execute_operations.clone().unwrap()\n                        )\n                    );\n                    if let Operation::User { application_id, .. } = operation {\n                        mandatory.remove(application_id);\n                    }\n                }\n                Transaction::ReceiveMessages(incoming_bundle)\n                    if incoming_bundle.action == MessageAction::Accept =>\n                {\n                    for pending in incoming_bundle.messages() {\n                        if let Message::User { application_id, .. } = &pending.message {\n                            mandatory.remove(application_id);\n                        }\n                    }\n                }","sourceCodeStart":1584,"sourceCodeEnd":1620,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-chain/src/chain.rs#L1584-L1620","documentation":"check_app_permissions (linera-chain/src/chain.rs:1585) enforces the chain's ApplicationPermissions: when the execute_operations allowlist is set (via the SetApplicationPermissions admin operation), every non-exempt operation's application must be on the list (chain.rs:1601-1607). Exempt system operations (e.g., changing the permissions themselves) bypass the check and additionally clear the mandatory-application requirement.","triggerScenarios":"Submitting a user operation whose application_id is not in the allowlist configured on the chain; calling a system operation that is not exempt (not in is_exempt_from_permissions) on a restricted chain; a chain restricted to app X receiving a transfer initiated by app Y.","commonSituations":"Regulated or app-curated chains configured with execute_operations permissions; deploying a new app version and forgetting to allowlist it; wallet clients defaulting to a fungible-token app not included in the chain's permission set.","solutions":["Only submit operations from applications on the chain's allowlist (query application_permissions from chain state)","To enable a new app, submit the exempt ChangeApplicationPermissions system operation first to extend the allowlist, then send the operation","If the restriction is wrong, update permissions via an exempt admin operation in its own step"],"exampleFix":"// before: submitting a restricted app's operation directly\nclient.submit_block(vec![Transaction::ExecuteOperation(user_op)]).await?; // AuthorizedApplications\n\n// after: widen the allowlist first, then submit\nclient.submit_block(vec![Transaction::ExecuteOperation(Operation::system(\n    SystemOperation::ChangeApplicationPermissions(ApplicationPermissions {\n        execute_operations: Some(new_set), ..\n    }),\n))]).await?;\nclient.submit_block(vec![Transaction::ExecuteOperation(user_op)]).await?;","handlingStrategy":"validation","validationCode":"// Check permissions client-side before submitting (mirrors chain.rs:1601-1607):\nlet perms = client.chain_info(chain_id).await?.info.application_permissions;\nfor op in block.operations() {\n    if !op.is_exempt_from_permissions()\n        && !perms.can_execute_operations(&op.application_id())\n    {\n        anyhow::bail!(\"operation app {:?} not in execute_operations allowlist\", op.application_id());\n    }\n}","typeGuard":"fn operation_allowed(perms: &ApplicationPermissions, op: &Operation) -> bool {\n    op.is_exempt_from_permissions() || perms.can_execute_operations(&op.application_id())\n}","tryCatchPattern":"match result {\n    Err(ChainError::AuthorizedApplications(allowed)) => {\n        // `allowed` lists the permitted apps: either switch to one of them, or first\n        // submit an exempt ChangeApplicationPermissions op to extend the allowlist\n    }\n    other => other?,\n}","preventionTips":["Cache and consult the chain's application_permissions alongside balances","After deploying new app versions, verify they are on the allowlist before use","Remember permission-change operations are exempt and can bootstrap access"],"tags":["linera","application-permissions","allowlist","operations","rust"],"backgroundTag":"operation-not-in-app-allowlist","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}