Zed Live installation does not survive the night

Hello!

We have an issue with the reliability of the Zed Cameras. We replicate in our code the example of the SDK: zed-sdk/object detection/image viewer/cpp at master · stereolabs/zed-sdk · GitHub

In a windows 11 IoT enterprise we digest the USB feed with NVidia RTX A4000 and RTX A5000 graphic cards.

But at some point after the 3rd hour or so, we get a grabFrame() error, it says that a CUDA error has occurred. From then on, we get no feed and we cannot close and reopen the camera, we have found no recovery option. If we close and reopen the application, including the openGL context, it complains about the architecture of the graphics card and says we need a newer one to be able to open the camera.

Ideally we would like to run this setup around the clock. Thank you in advance

Our opening params

 ZED_TRACE(QString("OPENING CAMERA [%1], Mode: %2").arg(m_serial, modeStr()));
m_camera = new sl::Camera;
sl::RESOLUTION res = sl::RESOLUTION::HD720;

switch (m_mode) {
case ZedLow:
    m_fps = 15;
    res = sl::RESOLUTION::HD720;
    break;
case ZedMed:
    m_fps = 30;
    res = sl::RESOLUTION::HD720;
    break;
case ZedMed2:
    m_fps = 15;
    res = sl::RESOLUTION::HD1080;
    break;
case ZedHigh:
    m_fps = 30;
    res = sl::RESOLUTION::HD720;
    break;
case ZedHigh2:
    m_fps = 30;
    res = sl::RESOLUTION::HD1080;
    break;
}

sl::InitParameters initParams {};
initParams.sdk_verbose = 0;
#ifdef ZED_NOISY_DEBUG
initParams.sdk_verbose = 1;
#endif
initParams.camera_fps = m_fps;
initParams.camera_resolution = res;
initParams.open_timeout_sec = 10.f;
initParams.camera_disable_self_calib = true;
initParams.depth_mode = sl::DEPTH_MODE::NEURAL_LIGHT;
initParams.coordinate_units = sl::UNIT::METER;
// initParams.grab_compute_capping_fps = qMin(m_fps, 30);  /// REVIEW WHEN OTHER PROBLEMS SOLVED
initParams.async_grab_camera_recovery = false; // We manage recovery
initParams.enable_image_enhancement = false;
initParams.enable_image_validity_check = false;
initParams.depth_stabilization = 0;
initParams.input.setFromSerialNumber(m_serial.toInt());

emit startOpenTimerRequested();
auto const err = m_camera->open(initParams);
emit stopOpenTimerRequested();

if (err != sl::ERROR_CODE::SUCCESS)
{
    // *** Errors Found:
    // - CAMERA_NOT_DETECTED: Bad USB connection. If Camera not connected, this point is not reached
    // - CORRUPTED_SDK_INSTALLATION: AI Resource Not Found, error trying to download it. No internet connection.
    // *** Possible Errors:
    // - NOT_ENOUGH_GPU_MEMORY, CUDA_ERROR, MODULE_NOT_COMPATIBLE_WITH_CUDA_VERSION
    closeCamera();
    return err;
}

m_cameraReady = true;
ZED_TRACE("OPENED");
return sl::ERROR_CODE::SUCCESS;
}

And our Loop function, that runs on another thread:

    void ZEDCamera::loop()
{
    ZED_TRACE("Start Camera Loop Thread");
    setStatus(OpeningCamera);
    
    // --- Phase 1: Graphics Initialization Sync ---
    while (!m_gfxReady && m_isAlive) {
        if (m_instances == 0 && m_trackings == 0) {
            m_thread->msleep(100);
            continue;
        }
        
        emit gfxInitializationRequested();
        m_thread->msleep(64); // Wait for GL context to bind
    }
    
    // Loop variables
    sl::ERROR_CODE err = sl::ERROR_CODE::SUCCESS;
    int frameErrorCount = 0;
    const int errorTries = 5000;
    int openRetryCount = 0;
    int retryOnSecs = 30;
    bool isFirstOpen = true;
    QTime retryTime = QTime::currentTime();
    
    auto triggerRestart = [&](int seconds) {
        ZED_TRACE(QString("Restarting Camera (Delay: %1s)...").arg(seconds));
        closeCamera(); // 1. MUST BE FIRST
        sl::Camera::reboot(m_serial.toInt()); // 2. Hardware reset
        
        m_restartCamera = false;
        retryTime = QTime::currentTime();
        retryOnSecs = seconds;
        
        setCameraInfo("🟡 Hardware reset triggered. Waiting for USB re-enumeration...");
    };
    
    // --- Phase 2: Main Operational Loop ---
    while (m_isAlive.load(std::memory_order_relaxed)) {
        
        // A) CONNECTION MANAGEMENT
        if (!m_cameraReady) {
            if (!isFirstOpen && retryTime.secsTo(QTime::currentTime()) < retryOnSecs) {
                m_thread->msleep(200);
                continue;
            }
            
            setCameraInfo("🟡 Initializing camera...");
            
            if (!isFirstOpen) {
                ZED_TRACE(QString("Retry Attempt %1. Cooldown: %2s")
                              .arg(openRetryCount).arg(retryOnSecs));
            }
            
            err = openCamera();
            
            if (err != sl::ERROR_CODE::SUCCESS) {
                isFirstOpen = false;
                openRetryCount++;
                retryTime = QTime::currentTime();
                
                setCameraError(
                    err,
                    "Open Camera",
                    QString("     Connection retry on %1 secs").arg(retryOnSecs)
                    );
                
                if (openRetryCount > 1000) {
                    setCameraInfo("🔴 Camera Not Found");
                    break;
                }
                continue;
            }
            
            // Success
            isFirstOpen = false;
            openRetryCount = 0;
            frameErrorCount = 0;
            setStatus(CameraOk);
            setCameraInfo("🟢 Ready");
        }
        
        // B) TRACKING & AI SYNC
        if (m_cameraReady) {
            if (m_trackings > 0 && !m_trackingReady && m_status != ErrorTracking) {
                setStatus(InitializingTracking);
                setCameraInfo("🟡 Initializing Camera Tracking...");
                
                err = initializeTracking();
                
                if (err != sl::ERROR_CODE::SUCCESS) {
                    setStatus(ErrorTracking);
                    setCameraError(err, "AI Optimization");
                } else {
                    setStatus(CameraOk);
                    setCameraInfo("🟢 Ready");
                }
            }
            else if (m_trackings == 0 && m_trackingReady) {
                finalizeTracking();
            }
        }
        
        // C) MANUAL RESTART CHECK
        if (m_restartCamera) {
            triggerRestart(15);
            continue;
        }
        
        // D) GRAB & PROCESS
        sl::ERROR_CODE grabErr = grabFrame();
        sl::ERROR_CODE viewErr =
            (grabErr == sl::ERROR_CODE::SUCCESS)
                ? generateFrameViews()
                : grabErr;
        
        if (grabErr == sl::ERROR_CODE::SUCCESS &&
            viewErr == sl::ERROR_CODE::SUCCESS)
        {
            frameErrorCount = 0;
            
            if (generateBoxTracking()) {
                static int frameGood = 0;
                if (++frameGood % 600 == 0) {
                    emit keepAliveConfirmed();
                    frameGood = 0;
                }
            }
            
            m_thread->msleep(2);
            continue;
        }
        
        // E) ERROR HANDLING
        err = (grabErr != sl::ERROR_CODE::SUCCESS) ? grabErr : viewErr;
        frameErrorCount++;
        
        if (err == sl::ERROR_CODE::CAMERA_REBOOTING ||
            err == sl::ERROR_CODE::CUDA_ERROR)
        {
            ZED_TRACE(QString(">>> CRITICAL ERROR [%1]. Forcing Reset.")
                          .arg(skCameraError(err)));
            
            setStatus(ErrorTracking);
            setCameraInfo("🔴 Camera Disconnected.\n     Trying to reconnect. Please wait.");
            
            triggerRestart(30);
        } else {
            if (frameErrorCount % 1000 == 0) {
                ZED_TRACE(QString(">>> Grab Error: %1. Counter: %2/%3")
                              .arg(skCameraError(err))
                              .arg(frameErrorCount)
                              .arg(errorTries));
                
                setCameraError(err, "Grab Frame");
            }
            
            if (frameErrorCount >= errorTries) {
                ZED_TRACE(">>> Error threshold reached. Restarting...");
                setStatus(ErrorTracking);
                triggerRestart(30);
            } else {
                m_thread->msleep(500);
            }
        }
    }
    
    // --- Phase 3: Exit Logic ---
    closeCamera();
    
    if (m_status != ErrorOpen && m_status != ErrorTracking) {
        setStatus(CameraClosed);
    }
    
    emit gfxFinalizationRequested();
    ZED_TRACE("End Loop Thread");
}

Hi @Tomas-Skandal
What ZED SDK version are you using?

I recommend you perform a more reliable grab error check on the sign of the returned value of the grab function:

  • Negative values are warnings
  • Positive values are errors
  • 0 is good, no errors

If you enabled the frame status check, it can return warnings (sl::ERROR_CODE::CORRUPTED_FRAME) when the scene is dark, and your application would stop.

Thank you, we changed it, but CUDA_ERROR is error 18, and NO_GPU_COMPATIBLE is error code 2, which are the ones we got. We get CUDA_ERROR on grabFrame() until we close and reopen, then we get NO_GPU_COMPATIBLE

Also the zed sdk version are both 5.2.2 with tensor 10.13_v5 with CUDA 13.2 and drivers 595.71 as well as 5.0.0 with tensor 10.9_v5 with CUDA 12.8 with NVIDIA Drivers 573.96.

Regardless of which, we end up with this behavior

Are you using a laptop? Is it possible that it disables the GPU for energy saving?

We are using Windows 11 IoT enterprise servers with USB powersave and sleep disabled via device manager, as well as power plan controls, also any feature regarding USB power savings is disabled in BIOS

Of course these servers are not laptops

This is the weird behavior. If you had a problem with drivers or CUDA, you would get this error from the very beginning, not after hours of flawless run.

Do you have a log of the application showing the error?

Hello!
I just left it running with sdk_verbose flag set to on in two machines and will get back to you. Unfortunately it says at the beginning that the log level of the verbosity is INFO, is there any verbose DEBUG level we should be aware of? In camera.hpp only sdk_verbose = 1 is mentioned

We have this in our logs this time:

04-04-2026 00:16:34 | INFO  | [ZEDCamera << PLUGIN >> | 32773034] :: ZED KEEPALIVE RECEIVED (Count: 10969)
04-04-2026 00:16:38 | INFO  | [ZEDCamera << PLUGIN >> | 32773034] :: [THREAD HEARTBEAT] Plugin & Thread Alive | Iterations: 6580918 | GFX: OK | Cam: OK | Track: OK | Status: CameraOk | Instances: 2
04-04-2026 00:16:43 | INFO  | [ZEDCamera << PLUGIN >> | 32773034] :: [THREAD HEARTBEAT] Plugin & Thread Alive | Iterations: 6581069 | GFX: OK | Cam: OK | Track: OK | Status: CameraOk | Instances: 2
04-04-2026 00:16:48 | INFO  | [ZEDCamera << PLUGIN >> | 32773034] :: [THREAD HEARTBEAT] Plugin & Thread Alive | Iterations: 6581220 | GFX: OK | Cam: OK | Track: OK | Status: CameraOk | Instances: 2
04-04-2026 00:16:53 | INFO  | [ZEDCamera << PLUGIN >> | 32773034] :: [THREAD HEARTBEAT] Plugin & Thread Alive | Iterations: 6581370 | GFX: OK | Cam: OK | Track: OK | Status: CameraOk | Instances: 2
04-04-2026 00:16:54 | INFO  | [ZEDCamera << PLUGIN >> | 32773034] :: ZED KEEPALIVE RECEIVED (Count: 10970)
04-04-2026 00:16:58 | INFO  | [ZEDCamera << PLUGIN >> | 32773034\] :: \[THREAD HEARTBEAT] Plugin & Thread Alive | Iterations: 6581521 | GFX: OK | Cam: OK | Track: OK | Status: CameraOk | Instances: 2
04-04-2026 00:17:03 | INFO  | [ZEDCamera << PLUGIN >> | 32773034\] :: \[THREAD HEARTBEAT] Plugin & Thread Alive | Iterations: 6581672 | GFX: OK | Cam: OK | Track: OK | Status: CameraOk | Instances: 2
04-04-2026 00:17:08 | INFO  | [ZEDCamera << PLUGIN >> | 32773034\] :: \[THREAD HEARTBEAT] Plugin & Thread Alive | Iterations: 6581823 | GFX: OK | Cam: OK | Track: OK | Status: CameraOk | Instances: 2
04-04-2026 00:17:21 [2026-04-04 00:17:21 UTC][ZED][INFO] Detected Connection Failure. Trying to recover the camera with sn32773034…
04-04-2026 02:16:54 | INFO  | [ZEDCamera << PLUGIN >> | 32773034\] :: TrackingTimer: Keep Alive signal not received for 7200 secs. Forcing camera restart.

[CameraRelatedFunctions.cpp|attachment](upload://tat66yHfT0NpukGKAR9JUJBNF71.cpp) (14.2 KB)

Noting the distant timestamps, we can see that some call hangs when we have the issue that does not allow it to survive the night. We attach also the extract functions for the loop function so you can see we use something very similar to the example in github for object detection. Do note that your libs are closed source and that some parts do not build in debug mode, so this is eating up our development time like integrating any other api never did, since we need to launch it in release for it to fail anywhere between 3 and 8 hours later.

Please resend the example code because it’s not reachable.

The diff may have to do with why, I will attach it again. Excuse me, but I am unsure of how these sites work, so I probably did something wrong last time, I hope this time you can see the attachment

CameraRelatedFunctions.cpp (14.2 KB)

It is to Stereolabs advantage that we are testing of the c++ integration in various RTX A5000s and with a C++ + OpenGL codebase, so that we both achieve certain reliability. Stereolabs fits like a glove in our installations, as they are are battle tested IoT lighting and architecture custom solutions for high end clients. I understand answering tickets is busy work, but if I did pique your interest, do feel free to find them in https://poet.software/applications . We are very keen on finding a way to convince our clients that the Zed2i is the most interesting real time Ai based computer vision product integration for us, but we need to stabilize them into our product first. Thank you in advance for your work, Tomas.

From our side, we are still testing them nightly, this night we will run the code in the example we are trying to mimic, to rule out possible driver issues (** https://github.com/stereolabs/zed-sdk/tree/master/object%20detection/image%20viewer/cpp )**

Hi @Tomas-Skandal
A few observations concerning your code:

            ZED_TRACE(QString("Checking calib file for SN: %1").arg(serial));

            const QString confFileName = QString("SN%1.conf").arg(serial);
            const QString confFilePath = settingsDir.absoluteFilePath(confFileName);

            if (!QFile::exists(confFilePath)) {
                ZED_TRACE(QString("Calibration file %1 not found. Downloading...").arg(confFileName));

                const QString urlStr = QString("https://www.stereolabs.com/developers/calib/?SN=%1").arg(serial);
                QNetworkAccessManager manager;
                QNetworkRequest request((QUrl(urlStr)));

You do not need to perform this check. The ZED SDK automatically downloads the calibration file if it is not present on the host.

    if (err != sl::ERROR_CODE::SUCCESS)

Here, check whether err is minor (negative) or greater (positive) than sl::ERROR_CODE::SUCCESS.
Negative values are warnings, positive values are errors.

Everything else looks well done.

When you detect a camera failure, what is the exact SDK error?

I recommend you try to obtain more information using sl::toString(err) and sl::toVerbose(err).

Hello !

Real quick, as a context clarification, the zed camera feed is put on a shared OpenGL context, and the thread that runs the loop lives in a .dll to our main application, which is the one that exposes said shared context.

We replaced all our != checks for > checks and we are now running a test printing toVerbose err whenever we assign to err. It does not look like the Zed SDK actually puts out an error, it’s more like the thread where we run loop() stops responding. We will get back to you promptly after the next crash with the last sdk err if there ever was one that was printed.

We are also running the git example with sdk verbose flag on, and if that one fails to reliably keep itself alive we will let you know.

Thank you very much for the quick response, we hope to work together and resolve this matter

Hello again!

Great but confusing news, the zed seemed to survive the night, this time we used a compatible extra powered USB extender, we are suspecting that it has something to do with energy when idle, but in Windows devices all USB devices have “Allow computer to turn off device when not used” off, and in BIOS all USB power management options are set to no savings… Tonight we will run a different test that will attempt to tell us in which function of the SDK the Zed hangs, since waiting until our own KeepAlive thread signals and terminating the thread always seemed to be a recipe for crashing the application.

Excuse us for not giving you much to go on with today

Hello!

Today I have a lot of data to offer regarding this issue. 3 Zeds crashed this weekend on our test machines, all of them with similar symptoms. We left a heartbeat signal from inside our loop function that, when the thread would become blocked, would trigger a different function that would check the result of atomic bools used for tracing down the function where our threads block.

Turns out it is grabFrame() as per our logs:

  | INFO  | [ZEDCamera << PLUGIN >> | 31300192] :: C1: T [Before Grab Frame Call]
  | INFO  | [ZEDCamera << PLUGIN >> | 31300192] :: C2: F [After Grab Frame Call]
  | INFO  | [ZEDCamera << PLUGIN >> | 31300192] :: C3: F [After error checking]
  | INFO  | [ZEDCamera << PLUGIN >> | 31300192] :: C4: F [Before Gen Box Tracking]
  | INFO  | [ZEDCamera << PLUGIN >> | 31300192] :: C5: F [After Gen Box Tracking]
  | INFO  | [ZEDCamera << PLUGIN >> | 31300192] :: C6: F [After error checking]

our code for the loop() function that the thread runs in cpp is :

void ZEDCamera::loop()
{
    ZED_TRACE("Start Camera Loop Thread");
    setStatus(OpeningCamera);
    QElapsedTimer et;
#ifdef ZED_NOISY_DEBUG
    ZED_TRACE("ZED_NOISY_DEBUG: Thread started successfully. Entering Phase 1 (GFX Sync).");
    int gfxWaitWarnCount = 0;
#endif

    // --- Phase 1: Graphics Initialization Sync ---
    while (!m_gfxReady && m_isAlive) {

        if (m_instances == 0 && m_trackings == 0) {
            m_thread->msleep(100);
            continue;
        }

#ifdef ZED_NOISY_DEBUG
        // Print roughly every 1 second (15 * 64ms)
        if (++gfxWaitWarnCount % 15 == 0) {
            ZED_TRACE(QString("ZED_NOISY_DEBUG: Still waiting for GFX context to bind... m_gfxReady is false. Wait count: %1").arg(gfxWaitWarnCount));
        }
#endif

        emit gfxInitializationRequested();
        m_thread->msleep(64); // Wait for GL context to bind
    }

#ifdef ZED_NOISY_DEBUG
    if (m_isAlive) {
        ZED_TRACE("ZED_NOISY_DEBUG: Phase 1 Complete. GFX context bound successfully. Proceeding to main loop.");
    }
#endif

    // Loop variables
    sl::ERROR_CODE err = sl::ERROR_CODE::SUCCESS;
    int frameWarningCount = 0;
    int frameErrorCount = 0;
    const int warningTries = 10000;
    const int errorTries   = 10;
    int openRetryCount = 0;
    int retryOnSecs = 30;
    bool isFirstOpen = true;
    QTime retryTime = QTime::currentTime();

#ifdef ZED_NOISY_DEBUG
    uint64_t debugLoopCounter = 0;
    QElapsedTimer heartbeatTimer;
    heartbeatTimer.start();
#endif

    auto triggerRestart = [&](int seconds) {
        ZED_TRACE(QString("Restarting Camera (Delay: %1s)...").arg(seconds));
        closeCamera(); // 1. MUST BE FIRST: Close the software handle cleanly, freeing GPU/AI memory
        sl::Camera::reboot(m_serial.toInt(), true); // 2. Hard reset the hardware
        m_restartCamera = false;
        retryTime = QTime::currentTime();
        retryOnSecs = seconds; // Give Windows and the USB Controller time to re-enumerate the device
        setCameraInfo("🟡 Rebooting Camera. wait a few seconds...");
    };

    // --- Phase 2: Main Operational Loop ---
    while (m_isAlive.load()) {

        c1 = false;
        c2 = false;
        c3 = false;
        c4 = false;
        c5 = false;
        c6 = false;

#ifdef ZED_NOISY_DEBUG
        debugLoopCounter++;
        if (heartbeatTimer.hasExpired(10000)) { // <--- Safe check for 10000ms
            ZED_TRACE(QString("[THREAD HEARTBEAT] Plugin & Thread Alive | Iterations: %1 | GFX: %2 | Cam: %3 | Track: %4 | Status: %5 | Instances: %6")
                          .arg(debugLoopCounter)
                          .arg(m_gfxReady ? "OK" : "WAIT")
                          .arg(m_cameraReady ? "OK" : "WAIT")
                          .arg(m_trackingReady ? "OK" : "WAIT")
                          .arg(statusStr())
                          .arg(m_instances.load()));
            heartbeatTimer.restart();
        }
#endif

        // A) CONNECTION MANAGEMENT
        if (!m_cameraReady) {
            if (!isFirstOpen && retryTime.secsTo(QTime::currentTime()) < retryOnSecs) {
                m_thread->msleep(200);
                continue;
            }

            setCameraInfo("🟡 Initializing camera...");
            if (!isFirstOpen) {
                ZED_TRACE(QString("Retry Attempt %1. Cooldown: %2s").arg(openRetryCount).arg(retryOnSecs));
            }

            err = openCamera();
            ZED_TRACE_ERR("openCamera", err);

            if (err > sl::ERROR_CODE::SUCCESS) {
                isFirstOpen = false;
                openRetryCount++;
                retryTime = QTime::currentTime();

                setCameraError(err, "Open Camera", QString("     Connection retry on %1 secs").arg(retryOnSecs));

                if (openRetryCount > 1000) {
                    setCameraInfo("🔴 Camera Not Found");
                    break; // Hard exit loop
                }
                continue;
            }

            // Success: Reset state
            isFirstOpen = false;
            openRetryCount = 0;
            frameWarningCount = 0;
            frameErrorCount   = 0;
            setStatus(CameraOk);
            setCameraInfo("🟢 Ready");
        }

        // B) TRACKING & AI SYNC
        if (m_cameraReady) {
            if (m_trackings > 0 && !m_trackingReady && m_status != ErrorTracking) {
                setStatus(InitializingTracking);
                setCameraInfo("🟡 Initializing Camera Tracking...");

                err = initializeTracking();
                ZED_TRACE_ERR("initializeTracking", err);

                if (err != sl::ERROR_CODE::SUCCESS) {
                    setStatus(ErrorTracking);
                    setCameraError(err, "AI Optimization");
                } else {
                    setStatus(CameraOk);
                    setCameraInfo("🟢 Ready");
                }
            }
            else if (m_trackings == 0 && m_trackingReady) {
                finalizeTracking();
            }
        }

        // C) MANUAL RESTART CHECK (TestRequested or KeepAlive Timeout)
        if (m_restartCamera) {
            triggerRestart(15);
            continue;
        }

        c1 = true;

        // D.1) GET FRAME DATE (needed for views and tracking): this function LOCKS till there is a new frame
        auto grabErr = grabFrame();
        ZED_TRACE_ERR("grabFrame", grabErr);

        // D.2) GET FRAME VIEWS
        auto viewErr = (grabErr == sl::ERROR_CODE::SUCCESS) ? generateFrameViews() : grabErr;
        ZED_TRACE_ERR("generateFrameViews", viewErr);

        c2 = true;

        if (grabErr == sl::ERROR_CODE::SUCCESS && viewErr == sl::ERROR_CODE::SUCCESS) {
            frameWarningCount = 0;
            frameErrorCount   = 0;

            c3 = true;

            // D.3) GET TRACKING DATA
            if (!checkTracking() || generateBoxTracking()) {
                if (++m_frameGoodCounter % 600 == 0) {
                    emit keepAliveConfirmed();
                    m_frameGoodCounter = 0;
                }
            }

            c4 = true;

            m_thread->msleep(2); // Breath room for the GPU context

            continue; //D -> SUCCESS, go for next frame
        }

        // E) ERROR HANDLING
        c5 = true;

        err = (grabErr != sl::ERROR_CODE::SUCCESS) ? grabErr : viewErr;

        if (err < sl::ERROR_CODE::SUCCESS) { // Periodic error logging for "Soft" errors (like darkness)
            if (++frameWarningCount % 1000 == 0) {
                ZED_TRACE(QString(">>> Grab Warning: %1. Counter: %2/%3")
                              .arg(skCameraError(err)).arg(frameWarningCount).arg(warningTries));
                setCameraError(err, "Grab Frame");
            }
            if (frameWarningCount >= warningTries && err != sl::ERROR_CODE::CAMERA_REBOOTING) {
                ZED_TRACE(">>> Warning threshold reached. Restarting...");
                setStatus(ErrorTracking);
                triggerRestart(30);
            }
#ifdef ZED_NOISY_DEBUG
            ZED_TRACE(QString(">>> Grab Warning: %1. Counter: %2/%3")
                          .arg(skCameraError(err)).arg(frameWarningCount).arg(warningTries));
#endif
        }
        else { // Bad errors
            if (++frameErrorCount >= errorTries) {
                ZED_TRACE(">>> Error threshold reached. Restarting...");
                setStatus(ErrorTracking);
                triggerRestart(30);
            } else {
                // Wait a bit
                m_thread->msleep(500);
            }
#ifdef ZED_NOISY_DEBUG
            ZED_TRACE(QString(">>> Grab Error: %1. Counter: %2/%3")
                          .arg(skCameraError(err)).arg(frameErrorCount).arg(errorTries));
#endif
        }

        c6 = true;

    } // while (m_isAlive.load())

    // --- Phase 3: Exit Logic ---
#ifdef ZED_NOISY_DEBUG
    ZED_TRACE("ZED_NOISY_DEBUG: m_isAlive became false. Thread breaking out of Phase 2 Loop. Initiating Shutdown.");
#endif

    closeCamera();

    // Preserve Error statuses for the Frontend to see why we stopped
    if (m_status != ErrorOpen && m_status != ErrorTracking) {
        setStatus(CameraClosed);
    }

    emit gfxFinalizationRequested();
    ZED_TRACE("End Loop Thread");

    setCameraInfo("🔴 Camera Closed");
}
 

And we have SDK logs too. The one that the SDK puts out when we lose them is :

11-04-2026 05:37:10 6-04-11 05:37:10 UTC][ZED][INFO] Detected Connection Failure. Trying to recover the camera with sn32773034...

And for another camera:

11-04-2026 02:51:33 6-04-11 02:51:33 UTC][ZED][INFO] Detected Connection Failure. Trying to recover the camera with sn31300192...

So now we can confirm that in our setup we are having our thread blocked by the Zed SDK, with which we share an OpenGL context with, and thus losing tracking info until application reboot with no ability to recover from this issue, since the locked thread keeps the Zed busy.

We kindly await your response, we are in great need of your help,
Tomas

Hello!

We are very interested in updates on your end, we send Zeds with our proprietary technology to possible partners for them to try out our technology and how it interfaces with the real world, but when they test them exhaustively, the integration breaks at some point because of what we can only assume is a thread-locking grabFrame() issue.

We await your response,
Tomas