tinyhumansai/openhuman · error

Local-only privacy mode is active: this action needs externa

Error message

Local-only privacy mode is active: this action needs external service `{}`. Disable local-only mode in Settings to allow it.

What it means

enforce_egress blocks an outbound transfer because the session's privacy mode is local-only: the action would contact an external service, which local-only forbids. It fires before disclose-and-send so a refused transfer is neither reported as pending nor dispatched; the mode defaults to allow when no policy is installed, so this only fires under an explicit local-only session policy.

Source

Thrown at src/openhuman/security/egress/enforce.rs:163

}

/// Enforce the live privacy policy for an `anyhow`-returning egress site
/// (composio tool calls, backend integrations, cloud embeddings). Reads the live
/// mode (defaulting to `Standard`/allow when no session policy is installed) and
/// returns `Err(block_message)` when [`local_only_blocks`] refuses the transfer,
/// else `Ok(())`. Call this **before** the disclose-and-send (i.e. before
/// [`emit_external_transfer`](super::emit::emit_external_transfer)) so a blocked
/// transfer is neither disclosed as pending nor dispatched.
pub fn enforce_egress(desc: &EgressDescriptor) -> anyhow::Result<()> {
    let mode = current_privacy_mode();
    if local_only_blocks(mode, desc) {
        log::warn!(
            "[privacy][egress-enforce] LocalOnly BLOCK provider={} service={} reason={:?} — refused",
            desc.provider_slug,
            desc.service,
            desc.reason,
        );
        anyhow::bail!("{}", block_message(desc));
    }
    log::debug!(
        "[privacy][egress-enforce] privacy_mode={:?} provider={} service={} reason={:?} — permitted",
        mode,
        desc.provider_slug,
        desc.service,
        desc.reason,
    );
    Ok(())
}

/// Enforce the live privacy policy for an agent tool whose `execute` returns
/// `Ok(ToolResult::error(..))` on a denied action (the network tools). Returns
/// `Some(message)` — prefixed with [`POLICY_BLOCKED_MARKER`] so the agent loop
/// treats it as a hard, cross-turn policy block (no pointless retries) — when the
/// transfer is refused, else `None`. Call it before the disclose-and-send; on
/// `Some`, short-circuit with `Ok(ToolResult::error(message))`.
pub fn local_only_tool_block(desc: &EgressDescriptor) -> Option<String> {

View on GitHub (pinned to 7491200858)

Solutions

  1. Disable local-only mode in Settings if external access is intended.
  2. Choose a local/offline alternative for the action.
  3. Ask the user to relax the privacy policy for this session.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/openhuman/security/egress/enforce.rs:163 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/649bfc1d0c5a7789. Report an issue: GitHub.