Troubleshooting Guide¶
Solutions to common problems when using the LIFX Emulator.
Port Conflicts and Resolution¶
Port Already in Use¶
Problem: Server fails to start with "Address already in use"
Causes:
- Another emulator instance is running
- Another application is using port 56700
- Previous test didn't clean up properly
Solutions:
-
Find what's using the port:
-
Kill the process:
-
Use dynamic port allocation (best for tests):
-
Use port offset in parallel tests:
-
Wait between tests:
Port Permission Denied¶
Problem: Cannot bind to port (Linux/macOS)
Cause: Ports below 1024 require root privileges
Solutions:
-
Use port >= 1024 (recommended):
-
Don't run as root (security risk)
Discovery Failures and Debugging¶
Client Cannot Find Emulated Devices¶
Problem: LIFX client library discovers nothing
Diagnostic checklist:
-
Check emulator is running:
Should show:Emulator listening on 127.0.0.1:56700 -
Check bind address:
-
Check firewall:
-
Windows: Allow Python through Windows Firewall
- macOS: System Preferences → Security & Privacy → Firewall → Allow Python
-
Linux:
-
Check client port:
-
Ensure client is looking on the correct port
- Default LIFX port is 56700
-
If using custom port, client must match
-
Network isolation:
-
Docker containers need
--network hostor proper port mapping - VMs need bridged networking
-
WSL2 may need port forwarding
-
Enable verbose logging:
Discovery Works, but Device Not Responding¶
Problem: Client sees device but times out on commands
Solutions:
- Check target serial:
device = create_color_light("d073d5000001")
print(f"Device serial: {device.state.serial}")
# Client must target this exact serial
-
Check tagged packets:
-
Broadcast packets have
tagged=Truein header - Unicast packets have
tagged=Falseand specific target -
Emulator routes based on target field
-
Check ack_required and res_required flags:
# Client should set these flags appropriately
# ack_required=True → Device sends acknowledgment
# res_required=True → Device sends state response
- Enable packet logging:
Devices Discovered Multiple Times¶
Problem: Client sees duplicate devices
Cause: Multiple emulator instances or broadcast responses
Solutions:
-
Check for multiple instances:
-
Use unique serials:
-
Check network interfaces:
- Multiple interfaces may cause duplicate broadcasts
- Bind to specific interface to avoid this
Timeout Issues¶
Client Operations Timeout¶
Problem: Client commands timeout waiting for response
Diagnostic steps:
-
Increase client timeout: Check your client library documentation for details.
-
Check response scenarios:
-
Check async context:
-
Network latency:
Tests Timeout in CI/CD¶
Problem: Tests pass locally but timeout in CI
Solutions:
-
Use dynamic ports:
-
Increase pytest timeout:
-
Reduce test fixture scope:
-
Check CI resource limits:
-
CI runners may be slower than local machine
- Increase timeouts for CI environment
- Use conditional timeouts:
Protocol Errors and Interpretation¶
Invalid Packet Type Errors¶
Problem: "Unknown packet type" errors
Cause: Client sending unsupported packet type
Solution:
-
Check protocol version:
-
Emulator supports LIFX LAN Protocol (November 2025)
-
See https://github.com/LIFX/public-protocol for specification
-
Check packet type support:
-
Enable verbose logging:
Look for:Unknown packet type: XXX
Malformed Packet Errors¶
Problem: "Failed to unpack packet" errors
Causes:
- Incorrect header format
- Wrong packet structure
- Byte order issues
Solutions:
-
Check header format:
-
Header is exactly 36 bytes
- Target field is 8 bytes (6-byte MAC + 2 null bytes)
-
Packet type in bytes 32-33 (little-endian)
-
Verify packet structure:
-
Enable debug logging:
Acknowledgment Not Received¶
Problem: Client expects ack but doesn't receive it
Causes:
ack_requiredflag not set in header- Packet dropped by scenario configuration
- Network issues
Solutions:
-
Check ack_required flag:
-
Check scenarios:
-
Enable verbose logging:
Look for:TX: Acknowledgment (45) to ...
Performance Problems¶
Slow Test Execution¶
Problem: Tests take too long to run
Solutions:
-
Use appropriate fixture scopes:
-
Run tests in parallel:
-
Reduce device count:
-
Remove unnecessary delays:
-
Profile your tests:
High Memory Usage¶
Problem: Emulator consuming too much memory
Causes:
- Too many devices
- Large tile/zone counts
- Memory leak in test code
Solutions:
-
Limit device count:
-
Clean up properly:
-
Check for test isolation issues:
Packet Loss Under Load¶
Problem: Packets dropped at high throughput
Causes: - OS UDP buffer limits - CPU saturation - Network congestion
Solutions:
-
Increase OS UDP buffer:
-
Reduce packet rate:
-
Check CPU usage:
Platform-Specific Issues¶
Windows Issues¶
Problem: Tests fail only on Windows
Common issues:
-
Event loop policy:
-
Firewall prompts:
- Windows Defender may prompt to allow Python
- Allow for private networks
-
Or use 127.0.0.1 binding (no firewall prompt)
-
Path separators:
-
Line endings:
- Git may convert line endings (CRLF vs LF)
- Configure
.gitattributes:
macOS Issues¶
Problem: Tests fail only on macOS
Common issues:
- Firewall blocks UDP:
- System Preferences → Security & Privacy → Firewall
- Click "Firewall Options"
-
Add Python and allow incoming connections
-
Too many open files:
-
Gatekeeper blocking Python:
Linux Issues¶
Problem: Tests fail only on Linux
Common issues:
-
Port binding requires root (ports < 1024):
-
Too many open files:
-
SELinux or AppArmor restrictions:
WSL (Windows Subsystem for Linux) Issues¶
Problem: Issues specific to WSL
Common issues:
- Port forwarding:
- WSL2 uses virtual network
- Ports may not be accessible from Windows
-
Workaround: Use
0.0.0.0binding and Windows firewall rules -
Network latency:
- WSL2 has slight network overhead
-
May need longer timeouts
-
File permissions:
- Files on Windows filesystem (e.g., /mnt/c/) have weird permissions
- Use Linux filesystem (e.g., ~/projects/)
Logging and Debugging Techniques¶
Enable Verbose Logging¶
Basic logging:
import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
Emulator-specific logging:
CLI verbose mode:
Output:
RX: GetService (2) from ('127.0.0.1', 54321)
TX: StateService (3) to ('127.0.0.1', 54321)
RX: GetColor (101) from ('127.0.0.1', 54321) target=d073d5000001
TX: StateColor (107) to ('127.0.0.1', 54321)
Inspect Device State¶
During tests:
@pytest.fixture
async def emulator():
device = create_color_light("d073d5000001")
server = EmulatedLifxServer([device], "127.0.0.1", 56700)
async with server:
yield server, device # Expose device for inspection
async def test_color_change(emulator):
server, device = emulator
# ... send SetColor command ...
# Inspect device state
print(f"Device color: {device.state.color}")
print(f"Device power: {device.state.power_level}")
assert device.state.color.hue == expected_hue
Packet Capture with Wireshark/tcpdump¶
Capture UDP packets:
# Linux/macOS - tcpdump
sudo tcpdump -i lo -n udp port 56700 -X
# Wireshark
# Filter: udp.port == 56700
Analyze LIFX packets: - First 36 bytes: LIFX header - Bytes 32-33: Packet type (little-endian) - Remaining bytes: Payload
Use pytest Debugging¶
Drop into debugger on failure:
Drop into debugger on first failure:
Set breakpoint in test:
async def test_something(emulator):
device = ...
breakpoint() # Python 3.7+
# or
import pdb; pdb.set_trace()
Enable pytest output:**¶
Common Error Messages¶
"RuntimeError: Server not running"¶
Cause: Attempting to use server before starting
Fix:
# Wrong
server = EmulatedLifxServer([device], "127.0.0.1", 56700)
await send_command() # Server not started!
# Right
server = EmulatedLifxServer([device], "127.0.0.1", 56700)
async with server:
await send_command() # Server is running
"ValueError: Invalid serial format"¶
Cause: Serial number not 12 hex characters
Fix:
# Wrong
device = create_color_light("123")
device = create_color_light("d073d500001") # 11 chars
# Right
device = create_color_light("d073d5000001") # 12 chars
"TypeError: Object of type 'bytes' is not JSON serializable"¶
Cause: Trying to serialize device state with bytes
Context: Usually happens with custom serialization
Fix:
import base64
# Convert bytes to base64 string
serial_str = base64.b64encode(device.state.serial_bytes).decode('ascii')
"SyntaxError: 'await' outside async function"¶
Cause: Using async operations outside async context
Fix:
# Wrong
def test_device():
await server.start() # Can't await in sync function
# Right
async def test_device():
await server.start() # Now it works
# Or use asyncio.run()
def test_device():
asyncio.run(async_main())
"DeprecationWarning: There is no current event loop"¶
Cause: Python 3.10+ changed event loop behavior
Fix:
# In conftest.py
import pytest
import asyncio
@pytest.fixture(scope="session")
def event_loop():
loop = asyncio.new_event_loop()
yield loop
loop.close()
Getting Help¶
If you're still stuck after trying these solutions:
- Check existing issues: https://github.com/Djelibeybi/lifx-emulator/issues
- Search documentation: Use the search feature in the docs
- Ask in discussions: https://github.com/Djelibeybi/lifx-emulator/discussions
- File a bug report: https://github.com/Djelibeybi/lifx-emulator/issues/new
When reporting issues, include:
- Python version (python --version)
- Operating system (Linux/macOS/Windows, version)
- lifx-emulator version (pip show lifx-emulator)
- Minimal reproduction code
- Error messages and stack traces
- What you've already tried
See Also¶
- FAQ - Common questions and answers
- Best Practices - Patterns and anti-patterns
- Integration Testing - pytest patterns
- Glossary - Terminology reference