linera-io/linera-protocol · error · ExecutionError

UnauthorizedApplication

UnauthorizedApplication

Error message

ExecutionError::UnauthorizedApplication(app_id)

What it means

Linera's execution runtime rejects an application's outbound HTTP request when the chain's ApplicationPermissions do not allow it. The chain stores an optional make_http_requests list: None means every application may make HTTP requests, Some(list) means only the listed application IDs. This check runs in the shared BaseRuntime::perform_http_request (runtime.rs:947), so it applies to both contract and service HTTP oracle calls, and failing it aborts the whole block, not just the call.

Source

Thrown at linera-execution/src/runtime.rs:947

            read_size += key.len() + value.len();
        }
        this.resource_controller
            .track_bytes_read(read_size as u64)?;
        Ok(key_values)
    }

    fn perform_http_request(
        &mut self,
        request: http::Request,
    ) -> Result<http::Response, ExecutionError> {
        let mut this = self.inner();
        let app_permissions = this
            .execution_state_sender
            .send_request(|callback| ExecutionRequest::GetApplicationPermissions { callback })?
            .recv_response()?;

        let app_id = this.current_application().id;
        ensure!(
            app_permissions.can_make_http_requests(&app_id),
            ExecutionError::UnauthorizedApplication(app_id)
        );

        this.resource_controller.track_http_request()?;

        this.execution_state_sender
            .send_request(|callback| ExecutionRequest::PerformHttpRequest {
                request,
                http_responses_are_oracle_responses:
                    Self::LIMIT_HTTP_RESPONSE_SIZE_TO_ORACLE_RESPONSE_SIZE,
                callback,
            })?
            .recv_response()
    }

    fn assert_before(&mut self, timestamp: Timestamp) -> Result<(), ExecutionError> {
        let this = self.inner();

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Submit SystemOperation::ChangeApplicationPermissions from the chain owner, adding this application's ID to make_http_requests (or setting it to None to allow all apps on that chain).
  2. If the chain was opened with restrictive permissions, open or re-create the chain with ApplicationPermissions that include the app in make_http_requests.
  3. If you do not own the chain, ask its owner to update the permissions; the error cannot be bypassed from the application side.
  4. If permissions cannot be changed, remove the HTTP call from the application and feed the data in via operations or blobs instead.

Example fix

// before
let response = runtime.perform_http_request(request)?; // fails: UnauthorizedApplication

// after (one-time setup by the chain owner, then the call succeeds)
// chain.submit(SystemOperation::ChangeApplicationPermissions(
//     ApplicationPermissions { make_http_requests: Some(vec![app_id]), ..Default::default() }))
let response = runtime.perform_http_request(request)?;
Defensive patterns

Strategy: validation

Validate before calling

// Before running the app's block, check the chain's permissions (e.g. via the node client / GraphQL):
// let perms = node.chain_info(chain_id).await?.application_permissions;
let allowed = perms.make_http_requests
    .as_ref()
    .map_or(true, |ids| ids.contains(&app_id));
if !allowed {
    // submit ChangeApplicationPermissions first, or abort with a clear config error
}

Try / catch

match result {
    Err(ExecutionError::UnauthorizedApplication(app_id)) => {
        // deterministic until permissions change: do NOT retry;
        // report that app_id needs make_http_requests on this chain
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling ContractRuntime::perform_http_request or the service runtime's HTTP API from an application whose ID is not in the chain's make_http_requests list. Typically after a SystemOperation::ChangeApplicationPermissions set an explicit list that omits the app, or after OpenChain created the chain with restrictive permissions (e.g. ApplicationPermissions configured for a different app).

Common situations: Deploying an HTTP-calling app on a chain created for another application; updating permissions to Some(vec![...]) and forgetting the new app; re-publishing bytecode so the app gets a new ApplicationId without re-granting permission; copying a genesis or chain config with a restrictive permission list into a test setup.

Understand the failure class

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/6aa53fd0e38d7acf. Report an issue: GitHub.