Your script opened this camera an hour ago; now create_image_acquirer refuses the same device and throws AccessDeniedException with ID: -1005. The camera, the CTI file and the network are fine. The device is still open — nearly always by a previous acquirer of your own, most often a Jupyter kernel that outlived the last run. This guide gives you the reading of the -1005 status, a four-step search for the holder, the one-call release (ia.destroy()), the privilege argument that decides who may open what, and the try/finally pattern that keeps the conflict from returning. Everything here applies to any GigE, USB3 or CoaXPress camera driven through a GenTL producer, on the bench or on the line.
Why does create_image_acquirer throw AccessDeniedException?
create_image_acquirer raises AccessDeniedException when the GenTL producer refuses the device open because another acquirer already holds the camera: exclusive and control privileges allow exactly one owner, and a second owner request is rejected immediately with ID: -1005.
GenTL grants access to a device at open time through explicit privileges. Your host library passes the requested mode into the producer's open call (device.open is where your traceback dies), and the producer refuses a conflicting request on the spot. Exclusive and control are owner modes, and a device takes exactly one owner. A second owner request fails with ID: -1005 whether the first owner is your own forgotten acquirer or another program entirely.
Two consequences follow. The failure is immediate, so no timeout or retry clears it while the holder lives. And the refusal is symmetric: the same conflict appears when a vendor tool tries to open a camera your Python process already owns. That direction — GUI tool versus script — is worked through in GigE camera open fails in a second tool: exclusive control.
What does GenTL exception ID -1005 mean?
ID: -1005 is the producer's access-denied status: the refusal happened at the privilege check when your host library called the device open, so the camera is present and listed but not free to open.
The message carries three parts. 'Requested operation is not allowed' is the producer's refusal text. ID: -1005 is its numeric access-denied status. The empty source message means the camera itself added nothing: the refusal came from the producer's bookkeeping before any setting reached the device.
That is why the error says nothing about your configuration. Width, height, pixel format and trigger parameters were never evaluated, because the open never got that far. It also explains a confusing detail: the camera lists cleanly. Enumeration only collects announcements; it takes no privilege and opens nothing. A clean list combined with a denied open is the held-device signature, not a contradiction. If your open fails right after discovery and no acquirer of yours is alive, GenTL camera open failure after successful discovery walks the remaining causes.
Who is holding the camera right now?
The holder is nearly always one of four things: an acquirer you created earlier and never destroyed, a still-running interpreter that owns one, a separate process such as a viewer or a daemon, or another host on the network.
Search in this order; the first hit settles it on most benches:
- Your own variable. The acquirer you created earlier and still hold in a variable is the owner. Destroy it as shown below; no restart needed.
- A living interpreter you forgot. Notebooks are the classic trap: this morning's kernel still holds the open from a cell you no longer remember. Restart the kernel or close the session.
- Another process. A viewer utility, a polling daemon, a test harness, a second script under another user account. Close them in order of suspicion.
- Another host. A GigE camera serves one control connection, so a second machine on the same switch can own it. Disconnect that host before blaming your code.
A hard crash behaves differently: when the owning process dies, the operating system closes its connections and the producer frees the device, so the next open succeeds. A lockout that survives a crash means the holder is still alive somewhere. The Linux cleanup path after abnormal exits is the same one described in Release a camera after a crash on Linux: GigE restart fix.
How do you release the camera without a reboot?
Call ia.destroy() on the acquirer that owns the device, and the producer frees the camera immediately; if you have lost the reference, close the owning interpreter or process first, because a second open cannot succeed while the first holder lives.
Release is one call:
ia.destroy() # closes the device open; the producer frees the camera
ia = h.create_image_acquirer(0) # succeeds now
If you want a clean state as well, reset the Harvester and rebuild the list. h.reset() returns it to its initial state, which clears added CTI files, so add yours again before updating:
ia.destroy()
h.reset() # back to the initial state
h.add_cti_file(r'/your/producer.cti') # add your producer's .cti again
h.update_device_info_list() # update() and create() in newer host-library releases
ia = h.create_image_acquirer(0)
Newer host-library releases rename several of these calls — add_file, update, create — while the release logic stays the same.
Then make the pattern permanent:
ia = None # illustrative: your acquirer variable, initially unset
try:
ia = h.create_image_acquirer(0)
ia.start_image_acquisition()
with ia.fetch_buffer() as buffer:
component = buffer.payload.components[0]
frame = component.data.reshape(component.height, component.width)
# ... your processing ...
finally:
if ia is not None:
ia.destroy()
The finally block is the whole point: whether the run ends normally, on an exception or on a keyboard interrupt, the device open closes and the next create finds the camera free.
Which privilege should you pass to create_image_acquirer?
Leave the privilege argument alone for acquisition work: an owner mode (exclusive, or control when a monitor must observe) is the only mode that can configure the device and start acquisition, while read-only is strictly for watching.
The create_image_acquirer signature exposes a privilege argument, and the host library passes it straight into the producer's open call. The GenICam GenTL standard defines four access modes, from exclusive at the strictest end down to read-only:
| Privilege | Who may still open while you hold it | Use it for |
|---|---|---|
| Exclusive | Nobody | Normal acquisition: one owner, no interference |
| Control | Read-only connections | Your owner when a monitor must observe |
| Read-only | Other read-only connections | A second connection that only watches |
A read-only connection can neither configure the device nor start acquisition, so it is never the mode for your working acquirer. Owner mode for acquisition, read-only for watching. If the owner holds exclusive, even a read-only request is refused — the same ID: -1005 — so a monitoring tool that cannot get in is telling you the owner chose the strictest mode.
Several cameras in one process are not a conflict: each device takes its own acquirer, as laid out in Multiple GenTL cameras in one process: one acquisition object each. Conflicts come from two opens of one device, not from many devices in one process.
How do you verify the camera opens again?
Verify with a five-line script that rebuilds the list, opens the camera, starts acquisition, fetches one buffer and destroys the acquirer; if it completes, the privilege state is clean, and if it raises AccessDeniedException again, a holder is still alive.
Resist the urge to rerun the full application first:
h.update_device_info_list()
ia = h.create_image_acquirer(0)
ia.start_image_acquisition()
with ia.fetch_buffer() as buffer:
print(buffer.payload.components[0].width,
buffer.payload.components[0].height)
ia.destroy()
If the script completes, the privilege state is clean and the device is yours again; the printed width and height confirm a real frame, not just a listing. If it raises AccessDeniedException once more, a holder is still alive — go back to the search order above and work it again. Only then bring your application back, one module at a time, so a second holder cannot sneak in behind the first fix.
When the actual need is a refresh rather than a reopen, skip the open entirely: Restart a live camera preview without reopening the device keeps a running stream while you reconfigure around it.
When is AccessDeniedException not a second acquirer?
If AccessDeniedException appears on the very first open in a freshly started interpreter, widen the search: the open may target the wrong camera in the list, a hidden process may hold the device, or a second host may own it.
Three rarer causes cover the rest. First, the wrong device: index 0 in the list may be a camera another station already owns, especially after a re-enumeration reshuffled the order. Target devices by serial number — create_image_acquirer accepts serial_number alongside the index — so the list cannot hand your open to a neighbouring camera.
Second, a process you cannot see: a service account, a scheduled job, a tool left open in another desktop session. List the machine's running interpreters and acquisition tools before you conclude anything stranger.
Third, the file side: a wrong or unvalidated CTI file produces empty or wrong lists, not ID: -1005. GenTL producer shows an empty camera list: match the CTI covers that diagnosis, and GenTL CTI file added but no error: validate before you enumerate covers the silent-file case. On frame-grabber transports such as CoaXPress and Camera Link, access conflicts follow the same owner logic described in Frame grabber in use: find the owner and release access.
How do you structure acquisition so this never returns?
Structure acquisition so the conflict cannot return: one acquirer per device held in one deliberate variable, a try/finally block that destroys it on every exit path, opens targeted by serial number, and one Harvester per script.
Four habits remove the whole class of error:
-
One acquirer per device, in one deliberate variable. Never call
create_image_acquirertwice withoutdestroyin between, even in throwaway experiments. -
try/finally around the working loop, with
ia.destroy()in the finally block. Keyboard interrupts and exceptions close the device like a normal exit. - Open by serial number, not list index, so re-enumeration cannot point your open at a different camera.
-
One Harvester per script. Refresh the list with
update_device_info_listwhen hardware changes; reset only when you mean to start over, and re-add your CTI file afterwards.
With those in place, an AccessDeniedException means what it says: someone holds the device, and the search order above finds them in minutes.
If you are equipping a bench or a line rather than debugging one, choose the camera in the area scan cameras category or the camera finder, and the CoaXPress and Camera Link interface side in the frame grabbers category. The camera configurator steps through interface and resolution with you before you order. More enumeration and open problems sit on the systems topic page, and the team answers integration questions at contact.
Questions
Does h.reset() release a camera that is still open?
No. h.reset() returns the Harvester to its initial state, so you must add your CTI file and update the device list again, but the release that matters is ia.destroy() on the acquirer that owns the device open. Destroy the acquirer first, then reset. If you no longer hold a reference to the acquirer, exit the interpreter and let the operating system close the open for you.
Why does the device list look fine but the open still fails?
Enumeration and opening are separate steps. update_device_info_list only collects device announcements from the network or bus; it takes no privilege and opens nothing. The access check happens later, when create_image_acquirer asks the producer to open the device. A camera that lists cleanly and then denies the open is the classic signature of a device already held under exclusive or control privilege.
Can two programs share one machine-vision camera?
Only in one direction. The GenTL standard allows read-only connections alongside a control owner, so a monitor can watch while the acquisition program runs. Two owners never share one device: the second exclusive or control request is refused with ID: -1005. For concurrent acquisition and monitoring, open the owner with control privilege and the observer read-only, never two exclusive opens.
What does the privilege argument in create_image_acquirer do?
It selects the access mode your host library requests at device open: exclusive, control (with an exit-close variant) or read-only. Exclusive tolerates no other open; control allows read-only observers; read-only can neither configure the device nor start acquisition. Keep an owner mode for your working acquirer and pass read-only only for a second connection that watches.
Does a crashed script leave the camera locked forever?
No. The device open belongs to the process that created it; when that process dies, the operating system closes its connections and the producer frees the camera, so the next open succeeds. A lockout that outlives a crash means the holder is still alive: a background kernel, a daemon or another user's session. Find the living process and close it there.