hermes - ✅(Solved) Fix ACP permission bridge crashes when request_permission() returns None [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#13449Fetched 2026-04-22 08:06:32
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
closed ×1cross-referenced ×1

make_approval_callback() handles timeouts/exceptions from request_permission(), but not a None response. If the ACP permission coroutine resolves to None, the callback raises AttributeError instead of safely denying.

Error Message

AttributeError: 'NoneType' object has no attribute 'outcome'

Root Cause

make_approval_callback() handles timeouts/exceptions from request_permission(), but not a None response. If the ACP permission coroutine resolves to None, the callback raises AttributeError instead of safely denying.

Fix Action

Fixed

PR fix notes

PR #13457: fix(permissions): handle None response from ACP request_permission

Description (problem / solution / changelog)

What does this PR do?

This PR hardens the ACP ? Hermes permission-approval bridge by safely handling an unexpected None result from equest_permission, preventing attribute errors and defaulting to a safe deny.

Related Issue

Fixes #13449

Type of Change

  • ?? Bug fix (non-breaking change that fixes an issue)
  • ? New feature (non-breaking change that adds functionality)
  • ?? Security fix
  • ?? Documentation update
  • ? Tests (adding or improving test coverage)
  • ?? Refactor (no behavior change)
  • ?? New skill (bundled or hub)

Changes Made

  • Return "deny" when equest_permission resolves to None in the approval callback.
  • Add a unit test covering the None response case to ensure the callback denies safely.

How to Test

  1. Connect via an ACP client that sends an empty response to permission requests.
  2. Verify the permission is denied rather than throwing an exception.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) � or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys � or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows � or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide � or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior � or N/A

Changed files

  • acp_adapter/permissions.py (modified, +3/-0)
  • tests/acp/test_permissions.py (modified, +14/-0)

Code Example

outcome = response.outcome

---

import asyncio, threading
from acp_adapter.permissions import make_approval_callback

async def fake_request_permission_fn(session_id, tool_call, options):
    return None

loop = asyncio.new_event_loop()
thread = threading.Thread(target=loop.run_forever, daemon=True)
thread.start()
cb = make_approval_callback(fake_request_permission_fn, loop, "s1", timeout=1)
print(cb("echo hi", "demo"))

---

AttributeError: 'NoneType' object has no attribute 'outcome'
RAW_BUFFERClick to expand / collapse

Summary

make_approval_callback() handles timeouts/exceptions from request_permission(), but not a None response. If the ACP permission coroutine resolves to None, the callback raises AttributeError instead of safely denying.

Affected files / lines

  • acp_adapter/permissions.py:59-66

Why this is a bug

The approval bridge is an external-response boundary. It correctly treats exceptions/timeouts as deny:

  • future.result(timeout=timeout) inside try/except
  • exception path returns "deny"

But immediately afterward it unconditionally does:

outcome = response.outcome

So a falsey / malformed response crashes the approval path.

Minimal reproduction

import asyncio, threading
from acp_adapter.permissions import make_approval_callback

async def fake_request_permission_fn(session_id, tool_call, options):
    return None

loop = asyncio.new_event_loop()
thread = threading.Thread(target=loop.run_forever, daemon=True)
thread.start()
cb = make_approval_callback(fake_request_permission_fn, loop, "s1", timeout=1)
print(cb("echo hi", "demo"))

Observed locally:

AttributeError: 'NoneType' object has no attribute 'outcome'

Expected behavior

Malformed / empty permission responses should be treated like other failed permission requests and resolve to "deny".

Actual behavior

The callback raises before returning a decision.

Suggested investigation

Guard response / response.outcome before dereferencing and add a regression test for a None permission response.

extent analysis

TL;DR

Check the response object for None before accessing its attributes to prevent the AttributeError and ensure a safe denial in case of a malformed response.

Guidance

  • Verify that the response object is not None before trying to access its outcome attribute.
  • Add a conditional check to handle the case where response is None, treating it as a denial.
  • Consider adding a regression test to ensure this fix works as expected for None permission responses.
  • Review the make_approval_callback function to ensure it correctly handles all possible response types from request_permission.

Example

if response is not None:
    outcome = response.outcome
else:
    # Handle the case where response is None, e.g., return "deny"
    outcome = "deny"

Notes

This solution assumes that a None response should be treated as a denial. If other handling is required, the conditional check can be adjusted accordingly.

Recommendation

Apply the workaround by adding a conditional check for None responses to prevent the AttributeError and ensure a safe denial, as this directly addresses the identified issue without requiring version upgrades or significant code changes.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Malformed / empty permission responses should be treated like other failed permission requests and resolve to "deny".

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix ACP permission bridge crashes when request_permission() returns None [1 pull requests, 1 participants]