Troubleshooting
This guide covers common issues you might encounter while using the AP3 SDK and their solutions.
Installation Issues
Python Version Mismatch
Problem: ERROR: Package requires a different Python: 3.12.0 not in '>=3.13,<3.14'
Solution:
# Check your Python version
python --version
# Install Python 3.13 if needed
# macOS (Homebrew)
brew install python@3.13
# Ubuntu/Debian
sudo apt-get install python3.13
# Create venv with correct version
python3.13 -m venv .venv
source .venv/bin/activate
Binary Loading Errors
Problem: OSError: cannot load library 'libsanction_check_lib.dylib'
Solution:
-
Verify binaries are included:
python -c "from pathlib import Path; import ap3; print(list((Path(ap3.__file__).parent / 'operations/psi/binaries').glob('*')))" -
Check platform compatibility:
# macOS file /path/to/libsanction_check_lib.dylib # Should show: Mach-O 64-bit dynamically linked shared library arm64 # Linux file /path/to/libsanction_check_lib.so # Should show: ELF 64-bit LSB shared object, x86-64 -
Platform mismatch: Contact info@silencelaboratories.com for binaries for your platform
Configuration Issues
API Key Not Found
Problem: ValueError: GOOGLE_API_KEY environment variable not set
Solution:
# 1. Create .env file
cat > .env << 'EOF'
GOOGLE_API_KEY="your-key-here"
EOF
# 2. Load it in your code
from dotenv import load_dotenv
load_dotenv()
# 3. Verify it's loaded
import os
print("Key loaded!" if os.getenv('GOOGLE_API_KEY') else "Key missing!")
Agent Connection Refused
Problem: httpx.ConnectError: [Errno 61] Connection refused
Solution:
-
Check agent is running:
# Check if process is listening lsof -i :10002 # PSI Initiator lsof -i :10003 # PSI Receiver lsof -i :8080 # Host -
Verify correct URL:
import httpx # Test connection try: response = httpx.get("http://localhost:10002/") print(f"Agent responding: {response.status_code}") except httpx.ConnectError: print("❌ Agent not running or wrong URL") -
Check firewall:
# macOS - allow incoming connections # System Settings → Network → Firewall # Linux sudo ufw allow 10002 sudo ufw allow 10003 sudo ufw allow 8080
PSI Protocol Issues
Error Code -1 from Rust Library
Problem: ProtocolError: Failed to process PSI message 1: error code -1
Cause: This typically indicates a data format mismatch between initiator and receiver.
Solution:
-
Verify hash type consistency:
# Both sides must use same hash type # Initiator uses "Customer", Receiver uses "Sanction" # This is correct in the SDK -
Check argument order in FFI:
# The fixed version has correct order: # session_id, big_y, count, msg1, msg1_len, seed -
Verify sanction list format:
# Correct format: semicolon-joined sanction_list = ["Name1,ID1,Addr1", "Name2,ID2,Addr2"] sanction_data = ";".join(sanction_list) # This is done automatically
Empty Sanction List
Problem: PSI protocol fails with empty sanction list
Solution:
# Always check list is non-empty
if not san ction_list:
raise ValueError("Sanction list cannot be empty")
# Minimum 1 entry required
SANCTION_LIST = ["Default,Entry,Required"]
Session ID Mismatch
Problem: Different session IDs between initiator and receiver
Solution:
# Initiator generates session ID
session_id, state, msg1 = psi.initiate(customer_data)
# Pass the SAME session_id to receiver
msg2 = receiver_psi.initiate_receiver(session_id, msg1, sanction_list)
# Don't generate a new one!
Dot Product Issues
RNG Not Initialized
Problem: AttributeError: 'NoneType' object has no attribute
Solution:
# Always use context manager
with DotProduct(side="OB") as dp:
# RNG automatically initialized
session_id, msg1, state, shares, triples = dp.initiate([5, 3])
# RNG automatically cleaned up
# Or manual initialization
dp = DotProduct()
dp.rng_ptr = dp.create_rng()
# ... use it ...
dp.cleanup() # Don't forget!
Round Number Mismatch
Problem: ProtocolError: OB side processes only even rounds, got round 3
Solution:
# OB processes: 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 (even)
# CB processes: 3, 5, 7, 9, 11, 13, 15, 17, 19 (odd)
# OB (Opening party / initiator)
if round_num % 2 == 0:
state, msg = dp.process_round(round_num, state, incoming_msg)
# CB (Closing party / receiver)
if round_num % 2 == 1:
state, msg = dp.process_round(round_num, state, incoming_msg)
Agent Communication Issues
Message Not Received
Problem: Agent doesn't respond to messages
Solution:
-
Check agent logs:
# PSI demo logs tail -f /tmp/psi_initiator.log tail -f /tmp/psi_receiver.log tail -f /tmp/psi_host.log -
Verify message format:
# Correct A2A message format message_request = SendMessageRequest( id=message_id, params=MessageSendParams.model_validate({ "message": { "role": "user", "parts": [{"type": "text", "text": json.dumps(protocol_data)}], "messageId": message_id, "contextId": context_id } }) ) -
Check agent card:
async with httpx.AsyncClient() as client: resolver = A2ACardResolver(client, agent_url) card = await resolver.get_agent_card() print(f"Agent: {card.name}") print(f"URL: {card.url}")
Performance Issues
Slow Protocol Execution
Problem: PSI or Dot Product takes too long
Common Causes:
- Network latency - Use local agents for testing
- Large dataset - PSI scales with sanction list size
- Debug logging - Disable verbose logging in production
Solution:
import logging
# Production: Only warnings and errors
logging.basicConfig(level=logging.WARNING)
# Development: Info level
logging.basicConfig(level=logging.INFO)
# Debugging: Debug level
logging.basicConfig(level=logging.DEBUG)
High Memory Usage
Problem: Python process uses excessive memory
Solution:
# Clean up resources
with DotProduct() as dp:
# Resources automatically cleaned
pass
# For PSI
psi = SanctionCheck()
# ... use it ...
psi.cleanup() # Explicit cleanup if not using context manager
Gemini API Issues
Rate Limit Exceeded
Problem: 429 Too Many Requests
Solution:
import time
from google.api_core import retry
# Add retry logic
@retry.Retry(predicate=retry.if_exception_type(Exception))
def call_with_retry():
# Your Gemini API call
pass
# Or manual backoff
for attempt in range(3):
try:
response = agent.process(message)
break
except Exception as e:
if '429' in str(e):
time.sleep(2 ** attempt) # Exponential backoff
else:
raise
Quota Exhausted
Problem: Resource exhausted: Quota exceeded
Solution:
- Check your quota: Google AI Studio
- Use a different API key
- Implement request batching
- Switch to a lower-cost model
Common Error Messages
ImportError: cannot import name 'X' from 'ap3'
Cause: Outdated SDK version or incorrect import path
Solution:
# Update SDK
pip install --upgrade ap3-0.X.X-py3-none-any.whl
# Check correct import paths
from ap3.operations.psi import SanctionCheck # ✓ Correct
from ap3.psi import SanctionCheck # ✗ Wrong
pydantic.ValidationError: X field required
Cause: Missing required field in Pydantic model
Solution:
# Check model requirements
from ap3.types.directive import PrivacyIntentDirective
# All required fields
intent = PrivacyIntentDirective(
ap3_session_id="session_123", # Required
intent_directive_id="intent_001", # Required
operation_type="PSI", # Required
participants=["agent1", "agent2"], # Required
expiry="2025-12-31T23:59:59Z", # Required
signature=None # Optional
)
Debug Mode
Enable detailed debugging:
import logging
# Enable debug mode
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Specific module debugging
logging.getLogger('ap3.operations.psi').setLevel(logging.DEBUG)
logging.getLogger('httpx').setLevel(logging.WARNING) # Reduce noise
Getting Help
If you can't resolve your issue:
- Check Examples: Review working examples in
examples/directory - Search Issues: GitHub Issues
- Contact Support: info@silencelaboratories.com
- Report Bug: Include:
- AP3 version
- Python version
- Platform (macOS/Linux/Windows)
- Full error traceback
- Minimal reproduction code
Diagnostic Commands
Run these to gather information for support:
# System info
python --version
pip list | grep ap3
uname -a # Linux/macOS
systeminfo # Windows
# Test imports
python -c "import ap3; print(ap3.__version__); from ap3.operations.psi import SanctionCheck; from ap3.operations.sfe import DotProduct; print('✅ All imports successful')"
# Check binaries
python -c "from pathlib import Path; import ap3; print(list((Path(ap3.__file__).parent / 'operations').rglob('*.dylib')))"
python -c "from pathlib import Path; import ap3; print(list((Path(ap3.__file__).parent / 'operations').rglob('*.so')))"