Troubleshooting#
Symptoms, causes, and fixes for the most common issues encountered with pyFlir and FLIR A-series cameras.
Camera not found on discover()#
Symptom: discover() returns an empty list.
Cause: the camera is still booting, unreachable, or on a different subnet.
Fixes:
Wait for boot. The FLIR A6751sc takes 60–90 seconds from power-on before it responds to GigE Vision discovery. If
discover()returns nothing right after power-on, wait the full boot time and retry.Confirm the camera has an address and your host has a reachable IP on the same subnet. FLIR A-series cameras use DHCP; if no DHCP server is present they fall back to a link-local address (
169.254.x.x). Usetcpdumporarp -ato see the camera’s ARP broadcasts immediately after boot.On Linux, raise the kernel UDP receive buffer:
sudo sysctl -w net.core.rmem_max=16777216
Check that reverse-path filtering is not dropping replies from an unexpected subnet (
cat /proc/sys/net/ipv4/conf/ethX/rp_filter). Set it to2(loose mode) if needed.
Finding the camera IP on Linux (USB-to-GigE dongle)#
If the camera boots and gets an APIPA address you may not know which IP to use. Capture the ARP broadcast immediately after power-on:
sudo tcpdump -i enxa0cec86a36c8 -n arp
The camera broadcasts an ARP announcement within the first few seconds of boot. The source IP in that packet is the camera’s current address.
Persistent dongle IP with NetworkManager#
NetworkManager can remove manually-assigned link-local addresses from a dongle between boots. Create a persistent connection profile so the address survives reboots:
# Create or modify a connection profile named "camera"
nmcli connection modify camera \
ipv4.addresses 169.254.61.52/16 \
ipv4.method manual
nmcli connection up camera
ACCESS_DENIED on reconnect (stale CCP lock)#
Symptom: after a crashed kernel or Ctrl-C, cam.connect() raises
GVCPError: ACCESS_DENIED and retries for up to 90 seconds.
Cause: the previous session held GVCP control (CCP) and didn’t release it. The camera keeps the old session alive until its heartbeat timeout expires (up to 60 seconds on some firmware versions).
Fix: this is normal. Camera.connect() automatically retries in a loop
until the heartbeat expires. Wait up to 90 seconds. If it still fails, restart
the Jupyter kernel (or Python process) that may be holding the connection open,
then retry.
ValueError: invalid literal for int() during XML download#
Symptom: cam.download_xml() raises a ValueError about a hex address
without a 0x prefix.
Cause: FLIR cameras put bare hex values (e.g. 3fff8000) in the
FIRST_URL bootstrap register, without the 0x prefix required by the
pyGigEVision default parser.
Fix: this is handled automatically by pyFlir’s fetch_genicam_xml
implementation. If you see this error you may be using a stale version of
pyFlir; update with pip install --upgrade pyFlir.
INVALID_PARAMETER during XML download#
Symptom: cam.download_xml() raises GVCPError: INVALID_PARAMETER
partway through.
Cause: the FLIR A6751sc rejects READMEM requests whose byte count is not a multiple of 4. The stock pyGigEVision implementation can issue odd-sized reads on the last chunk.
Fix: handled automatically by pyFlir’s aligned read wrapper. See above for the update note.
Height reported as 513 instead of 512#
Symptom: cam.height, cam.get_roi(), or frame.shape[0] show 513
instead of the expected 512 (on a 640×512 sensor).
Cause: the A6751sc appends one telemetry/metadata row to each frame. The
Height register therefore reads 513 (512 image rows + 1 metadata row).
Fix: handled automatically after load_xml(). pyFlir reads the
SensorHeight register, detects the discrepancy, sets _metadata_rows = 1,
adjusts self.height = 512, and strips the extra row from every frame. All
user-facing values (cam.height, cam.get_roi(), frame.shape) reflect
the 512 usable image rows. The metadata row is accessible on
cam.last_metadata_rows.
Model shows “Xsc Series” instead of “A6751sc”#
Symptom: cam.model returns "Xsc Series" after discovery or connect.
Cause: the standard GigE Vision DeviceModelName register on FLIR cameras
returns the firmware platform name (“Xsc Series”), not the product SKU.
Fix: handled automatically after load_xml(). pyFlir reads the
FLIR-specific CameraModel register (address 0x4EA53C64) which contains
"A6751sc", and uses it to overwrite the discovery value.
Camera model / serial blank before load_xml()#
Symptom: cam.model or cam.serial are empty right after
cam.connect().
Cause: the A6751sc does not populate the standard GigE Vision device-info registers that pyGigEVision reads during discovery. The correct values live in FLIR-specific registers that can only be read after the GenICam XML is loaded.
Fix: cam.connect() auto-loads the XML from any cached
docs/camera_*.xml or camera_*.xml file in the working directory. After
that, cam.model == "A6751sc" and cam.serial == "00332" (or whichever
unit you have). If no cache exists, call cam.download_xml() first.
Live streaming lag that grows over time#
Symptom: a live display loop starts in sync but drifts further behind real time each second.
Cause: the display or processing code is slower than the camera frame rate. Frames accumulate in pyFlir’s internal GVSP queue and the loop processes them in order, each one staler than the last.
Fix: use latest=True in the read loop:
while True:
frame = cam.read(timeout=2.0, latest=True)
display(frame)
This drops intermediate frames when the consumer is slow but keeps displayed
latency bounded to one frame period. Use the default latest=False when you
need every frame (logging, measurement).