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
- Disable local-only mode in Settings if external access is intended.
- Choose a local/offline alternative for the action.
- 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.