Exception in callback: An item with the same key has already been added

Example Scenario: I have image A and B. I scan image A, then scanned image B. Both were doing as its supposed to do. But when I try to scan image A again, this error shows

Exception in callback: An item with the same key has already been added:

And the quad displaying on the target image is the quad for image B. According to debug logs, the image target for image A is still being retrieved correctly. Help me fix this.

Here’s the script:

using System.Diagnostics;
using UnityEngine;
using Vuforia;

public class SimpleCloudRecoEventHandler : MonoBehaviour
{
    CloudRecoBehaviour mCloudRecoBehaviour;
    bool mIsScanning = false;
    string mTargetMetadata = "";

    public ImageTargetBehaviour ImageTargetTemplate;

    void Awake()
    {
        mCloudRecoBehaviour = GetComponent<CloudRecoBehaviour>();
        mCloudRecoBehaviour.RegisterOnInitializedEventHandler(OnInitialized);
        mCloudRecoBehaviour.RegisterOnInitErrorEventHandler(OnInitError);
        mCloudRecoBehaviour.RegisterOnUpdateErrorEventHandler(OnUpdateError);
        mCloudRecoBehaviour.RegisterOnStateChangedEventHandler(OnStateChanged);
        mCloudRecoBehaviour.RegisterOnNewSearchResultEventHandler(OnNewSearchResult);
    }

    void Start()
    {
        // Register status change callback
        if (ImageTargetTemplate)
        {
            ImageTargetTemplate.OnTargetStatusChanged += OnTargetStatusChanged;
        }
    }

    void OnDestroy()
    {
        // Unregister event handlers when the handler is destroyed
        mCloudRecoBehaviour.UnregisterOnInitializedEventHandler(OnInitialized);
        mCloudRecoBehaviour.UnregisterOnInitErrorEventHandler(OnInitError);
        mCloudRecoBehaviour.UnregisterOnUpdateErrorEventHandler(OnUpdateError);
        mCloudRecoBehaviour.UnregisterOnStateChangedEventHandler(OnStateChanged);
        mCloudRecoBehaviour.UnregisterOnNewSearchResultEventHandler(OnNewSearchResult);

        if (ImageTargetTemplate)
        {
            ImageTargetTemplate.OnTargetStatusChanged -= OnTargetStatusChanged;
        }
    }

    public void OnInitialized(CloudRecoBehaviour cloudRecoBehaviour)
    {
        UnityEngine.Debug.Log("Cloud Reco initialized");
    }

    public void OnInitError(CloudRecoBehaviour.InitError initError)
    {
        UnityEngine.Debug.Log("Cloud Reco init error: " + initError.ToString());
    }

    public void OnUpdateError(CloudRecoBehaviour.QueryError updateError)
    {
        UnityEngine.Debug.Log("Cloud Reco update error: " + updateError.ToString());
    }

    public void OnStateChanged(bool scanning)
    {
        mIsScanning = scanning;

        if (scanning)
        {
            // Clear all known targets
            UnityEngine.Debug.Log("Scanning...");
        }
    }

    public void OnNewSearchResult(CloudRecoBehaviour.CloudRecoSearchResult cloudRecoSearchResult)
    {
        mTargetMetadata = cloudRecoSearchResult.MetaData;
        mCloudRecoBehaviour.enabled = false;

        if (ImageTargetTemplate)
        {
            // Enable the new result with the same ImageTargetBehaviour
            mCloudRecoBehaviour.EnableObservers(cloudRecoSearchResult, ImageTargetTemplate.gameObject);

            // Retrieve the ImageTargetBehaviour
            ImageTargetBehaviour imageTarget = ImageTargetTemplate.GetComponent<ImageTargetBehaviour>();

            // Find the VideoLoader on the Quad
            VideoLoader videoLoader = ImageTargetTemplate.GetComponentInChildren<VideoLoader>();

            if (videoLoader != null && imageTarget != null)
            {
                string videoUrl = FindObjectOfType<FirebaseManager>().GetGithubPageUrlByDocumentId(cloudRecoSearchResult.TargetName);
                if (!string.IsNullOrEmpty(videoUrl))
                {
                    videoLoader.OnTargetDetected(videoUrl, imageTarget);
                }
                else
                {
                    UnityEngine.Debug.LogError("Video URL not found for target: " + cloudRecoSearchResult.TargetName);
                }
            }
            else
            {
                UnityEngine.Debug.LogError("VideoLoader or ImageTargetBehaviour component not found.");
            }
        }
    }

    // Handle changes in target tracking status
    void OnTargetStatusChanged(ObserverBehaviour observerBehaviour, TargetStatus status)
    {
        // Retrieve the VideoLoader component from the child Quad
        VideoLoader videoLoader = ImageTargetTemplate.GetComponentInChildren<VideoLoader>();

        if (videoLoader != null)
        {
            // Show or hide the Quad based on tracking status
            bool isVisible = status.Status == Status.TRACKED;
            videoLoader.SetQuadVisibility(isVisible);
        }

        // Automatically restart scanning when the target is lost
        if (status.Status != Status.TRACKED && mCloudRecoBehaviour != null && !mIsScanning)
        {
            RestartScanning();
        }
    }

    private void RestartScanning()
    {
        mCloudRecoBehaviour.enabled = true;  // Re-enable Cloud Recognition
        mIsScanning = true;  // Update the scanning state
        mTargetMetadata = "";  // Clear the previous metadata
        UnityEngine.Debug.Log("Restarted scanning for new targets.");
    }
}

I don’t think this script is causing the error. It seems like something is trying to be added to a dictionary with the same key, but I don’t see any dictionary or Add in this script.

Its probably in one of the related scripts being accessed when you do the scan. You need to add a check if the key exists, then just update it instead of adding it. Or clear the dictionary before each scan if you don’t need to preserve all of them. You do have this comment but it’s not actually doing it

Same thoughts, I don’t really understand which dictionary the error is referring to. This is what chatGPT told me:

The error message “An item with the same key has already been added” typically occurs when a duplicate key is added to a dictionary or collection that requires unique keys. In your code, this is likely happening in Vuforia’s internal state management, especially when it reuses previously detected targets.

I would look into each of those scripts and try to find a dictionary or any sort of Add function call. It is probably being triggered by one of the callbacks in your original script. You may need to add some additional callback or function call to clear that dictionary before each scan.