Why do I get an KeyError when using Modules?

Hello,
I am currently working on a project on Determining Winners and Update them (they are vectors) . I implemented these function as seperate compiler to test their functionality and it works like a charm. But unfortunately this isn’t really my attended use case. I want it to work without an decryption and encryption step between the defiend circuits. So I tried using them as one big circuit and implemented in a module. I copy pasted my functions and inputset but on both approaches (one big circuit and module) I get the same Error of the following form:
KeyError: <concrete.fhe.representation.node.Node object at 0x7f473988d790>

How do I fix this error? Or are their other approaches to work without extra decryption and encrytion?
I would also pleased to know about what changes in the way the compiler works in the background, would be really interesting.

Best regards

Hello. To help you, we would need you to create a GitHub repository reproducing the problem, and you to tell us what command line to launch. Without a way to reproduce, we can barely help you. Thanks

Hello,

sorry for the late response. I got it kinda figured out. I don’t get this error anymore. But now I get an error:
RuntimeError: NoParametersFound

I read the documentation to e.g. simplifiy the circuit but don’t really know how. I get this error when I use the approach from the documentation on Retrieving a value within an encrypted array with an encrypted index.

I uploaded the file on github: /Luggarythmus/FHE_Test

Unfortunately I can’t provide a link here cause I am a new user.
Best regards

Hello

Once again, we need you to create a github repo and have your source code there, with instructions to repro, for us to be able to help you. Else, we are completely in the dark.

Could you provide that please?
Cheers

Hello

Unfortunately, I am not able to provide you a link in a post. There is an Error Message that says: I am not able to provide Links in a post, because I am a new user.

There is only one python file (test3.py). In my Virtual environment are the following packages:

concrete-python==2.10.0
contourpy==1.3.2
cycler==0.12.1
filelock==3.18.0
fonttools==4.58.4
fsspec==2025.3.2
importlib_resources==6.5.2
Jinja2==3.1.6
joblib==1.5.1
jsonpickle==4.0.5
kiwisolver==1.4.8
MarkupSafe==3.0.2
matplotlib==3.10.3
mpmath==1.3.0
networkx==3.4.2
numpy==1.26.4
nvidia-cublas-cu12==12.6.4.1
nvidia-cuda-cupti-cu12==12.6.80
nvidia-cuda-nvrtc-cu12==12.6.77
nvidia-cuda-runtime-cu12==12.6.77
nvidia-cudnn-cu12==9.5.1.17
nvidia-cufft-cu12==11.3.0.4
nvidia-cufile-cu12==1.11.1.6
nvidia-curand-cu12==10.3.7.77
nvidia-cusolver-cu12==11.7.1.2
nvidia-cusparse-cu12==12.5.4.2
nvidia-cusparselt-cu12==0.6.3
nvidia-nccl-cu12==2.26.2
nvidia-nvjitlink-cu12==12.6.85
nvidia-nvtx-cu12==12.6.77
packaging==25.0
pandas==2.3.0
pillow==11.2.1
pyparsing==3.2.3
python-dateutil==2.9.0.post0
pytz==2025.2
scikit-learn==1.7.0
scipy==1.15.3
setuptools==80.7.1
six==1.17.0
sympy==1.14.0
threadpoolctl==3.6.0
torch==2.7.0
triton==3.3.0
typing_extensions==4.13.2
tzdata==2025.2
wheel==0.45.1
z3-solver==4.13.0.0

I execute it with:

python test3.py

Because I am not allowed to provide a github link:
The content of the FHE function I want to compile is the following:

def homoLVQ1(weights, sample,l_sample,alpha):
    epochs = 1
    #weights = np.array(weights,dtype=object)
    # new = np.empty([len(weights),len(weights[0])])
    #weights_cp = copy.deepcopy(weights)
    weights_cp = fhe.identity(weights)
    weights = np.array(weights)
    

    # take the sample
    #distances = np.empty(weightscount,dtype=object)
    #distances = [0] * weightscount
    distances = []
    for w in range(len(weights) ):
        distance = 0
        for i in range(len(sample)):
            distance = distance + ((sample[i] * sample[i])-(2*sample[i]*weights[w][i])+(weights[w][i]*weights[w][i]))
            
        #distances[w] = distance 
        distances.append(distance)
    # distances = fhe.refresh(distances)
    

    min_value = distances[0]
    min_index = 0
    
    K = len(distances)
    # dtype object such that in different python objects can be stored
    # aka Tracer Object from concrete
    A = np.empty(K,dtype=object)

    A[0] = 1
    for i in range(1,K):
        A[i] = 0

    min_index_array=[]
    for k in range(0,K):
        C = min_value < distances[k] # result is an tracer object
        for r in range(1,k):
            A[r] = A[r] * C
        # negate C
        negate = 1 + C * (0-1)
        A[k] = negate
        min_value  = min_value + C * (distances[k]-min_value)
    

    
    min_index = fhe.zero()
    for i in range(len(A)):
        min_index +=  i * A[i]

    """
    #Komplexität dieser Implementierung höher
    for index, value  in enumerate(distances,start=0):
        comp = min_value>value
        min_value, min_index = min_value + (comp) * (value-min_value) , min_index + (comp) * (index-min_index)
    
    """
    """
    prototype = [0,0,0]
    for w in range(len(weights)):
                equal = (min_index == w)
                for i in range(len(weights[w])):
                    prototype[i] += (equal * weights[w][i])

    
    for w, weight in enumerate(weights):
        equal = (min_index == w)
        prototype = [p + equal * w_i for p, w_i in zip(prototype, weight)]
    """
    
    prototype = [0,0,0]
    all_indices = np.arange(len(weights))
    index_selection = min_index == all_indices # one hot encoded array
    #selection_and_zeros = weights[0][0] * index_selection
   
    
    for w,s in zip(weights_cp,index_selection):
        for t in range(len(w)):
            prototype[t] += w[t] * s
    

    """
    block_size = len(weights[0])
    #index_selection = np.repeat(index_selection,block_size) # [0,0,0,1,1,1]
    expanded = []
    for value in index_selection:
        for _ in range(block_size):
            expanded.append(value)
    print(len(expanded))
    components =[]
    for i in range(len(weights)):
        for j in range(len(weights[0])):
            components.append(weights[i][j])

    i = 0
    for c , s in zip(components,expanded):
        prototype[i%3] = c * s
        i+=1
    
    """
    """
    for w,s in zip(weights_cp,index_selection):
        prototype += w *s
    """
    #selection = np.sum(selection_and_zeros)
   

    # prototype = weights[0]

    winner_class = min_index
    
    equal = l_sample == winner_class
    
    
    # compute psi for the attraction repelling scheme, holds -1 or 1
    negate = 1 + (equal) * (0-1)
    psi = equal - negate
    
    for i in range(len(prototype)):
        nom = psi * (sample[i] - prototype[i])
        denom = alpha
        prototype[i] = prototype[i] + fhe.multivariate(lambda nom, denom: nom// denom)(nom, denom)
        # prototype[i] = fhe.refresh(prototype[i])
    
    """
    for w in range(len(weights)):
        mask = (min_index == w)
        for i in range(len(weights[w])):
            weights[w][i] = weights[w][i] + mask * (prototype[i]-weights[w][i])
    """
    alpha +=1
    

    return tuple(prototype)

It includes some alternatives that I tried, but they also don’t work.

Unfortunately, I am not able to provide you a link in a post. There is an Error Message that says: I am not able to provide Links in a post, because I am a new user.

Oh, sorry I didn’t understand that. Let me see internally what we can do here.
And in the meantime, maybe our team can look at your code.

No problem thank you for your time

Looked quickly at your code: it’s not complete / self sufficient (eg, you don’t compile the function here). We need the complete stuff to reproduce an issue, please

of course sorry I forgot that: here is the complete content of my python file:

from concrete import fhe
import numpy as np
import copy

# configuration = fhe.Configuration(comparison_strategy_preference=fhe.ComparisonStrategy.THREE_TLU_CASTED)
def homoLVQ1(weights, sample,l_sample,alpha):
    epochs = 1
    #weights = np.array(weights,dtype=object)
    # new = np.empty([len(weights),len(weights[0])])
    #weights_cp = copy.deepcopy(weights)
    weights_cp = fhe.identity(weights)
    weights = np.array(weights)
    

    # take the sample
    #distances = np.empty(weightscount,dtype=object)
    #distances = [0] * weightscount
    distances = []
    for w in range(len(weights) ):
        distance = 0
        for i in range(len(sample)):
            distance = distance + ((sample[i] * sample[i])-(2*sample[i]*weights[w][i])+(weights[w][i]*weights[w][i]))
            
        #distances[w] = distance 
        distances.append(distance)
    # distances = fhe.refresh(distances)
    

    min_value = distances[0]
    min_index = 0
    
    K = len(distances)
    # dtype object such that in different python objects can be stored
    # aka Tracer Object from concrete
    A = np.empty(K,dtype=object)

    A[0] = 1
    for i in range(1,K):
        A[i] = 0

    min_index_array=[]
    for k in range(0,K):
        C = min_value < distances[k] # result is an tracer object
        for r in range(1,k):
            A[r] = A[r] * C
        # negate C
        negate = 1 + C * (0-1)
        A[k] = negate
        min_value  = min_value + C * (distances[k]-min_value)
    

    
    min_index = fhe.zero()
    for i in range(len(A)):
        min_index +=  i * A[i]

    """
    #Komplexität dieser Implementierung höher
    for index, value  in enumerate(distances,start=0):
        comp = min_value>value
        min_value, min_index = min_value + (comp) * (value-min_value) , min_index + (comp) * (index-min_index)
    
    """
    """
    prototype = [0,0,0]
    for w in range(len(weights)):
                equal = (min_index == w)
                for i in range(len(weights[w])):
                    prototype[i] += (equal * weights[w][i])

    
    for w, weight in enumerate(weights):
        equal = (min_index == w)
        prototype = [p + equal * w_i for p, w_i in zip(prototype, weight)]
    """
    
    prototype = [0,0,0]
    all_indices = np.arange(len(weights))
    index_selection = min_index == all_indices # one hot encoded array
    #selection_and_zeros = weights[0][0] * index_selection
   
    
    for w,s in zip(weights_cp,index_selection):
        for t in range(len(w)):
            prototype[t] += w[t] * s
    

    """
    block_size = len(weights[0])
    #index_selection = np.repeat(index_selection,block_size) # [0,0,0,1,1,1]
    expanded = []
    for value in index_selection:
        for _ in range(block_size):
            expanded.append(value)
    print(len(expanded))
    components =[]
    for i in range(len(weights)):
        for j in range(len(weights[0])):
            components.append(weights[i][j])

    i = 0
    for c , s in zip(components,expanded):
        prototype[i%3] = c * s
        i+=1
    
    """
    """
    for w,s in zip(weights_cp,index_selection):
        prototype += w *s
    """
    #selection = np.sum(selection_and_zeros)
   

    # prototype = weights[0]

    winner_class = min_index
    
    equal = l_sample == winner_class
    
    
    # compute psi for the attraction repelling scheme, holds -1 or 1
    negate = 1 + (equal) * (0-1)
    psi = equal - negate
    
    for i in range(len(prototype)):
        nom = psi * (sample[i] - prototype[i])
        denom = alpha
        prototype[i] = prototype[i] + fhe.multivariate(lambda nom, denom: nom// denom)(nom, denom)
        # prototype[i] = fhe.refresh(prototype[i])
    
    """
    for w in range(len(weights)):
        mask = (min_index == w)
        for i in range(len(weights[w])):
            weights[w][i] = weights[w][i] + mask * (prototype[i]-weights[w][i])
    """
    alpha +=1
    

    return tuple(prototype)


if __name__=="__main__":
    
    #lvqCompiler = fhe.Compiler(homoLVQ1,{"weights":"encrypted","samples":"encrypted", "labels":"encrypted", "alpha":"encrypted"})
    #lvqCompiler = fhe.Compiler(homoLVQ1,{"weights":"encrypted","samples":"encrypted", "labels":"encrypted", "alpha":"clear"})   
    lvqCompiler = fhe.Compiler(homoLVQ1,{"weights":"encrypted","sample":"encrypted","l_sample":"encrypted","alpha":"encrypted"})
    samples = [[40, 152, 144], [16, 152, 136], [139, 0, 16], [131, 32, 22], [128, 32, 32], [0, 136, 160], [160, 0, 0], [27, 160, 128], [144, 16, 16], [136, 32, 32], [32, 144, 128], [48, 144, 144], [0, 160, 160], [16, 136, 144], [147, 24, 16], [160, 20, 32]]
    labels = [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0]
    weights= [[160, 112, 16], [160, 160, 160]]


    configuration = fhe.Configuration(
        enable_unsafe_features=True,
        use_insecure_key_cache=True,
        insecure_key_cache_location=".keys",
        #compiler_debug_mode=True,
        #compiler_verbose_mode=True,
        #security_level = 128,
        #show_optimizer=True,
        # To enable displaying progressbar
        show_progress=True,
        # To enable showing tags in the progressbar (does not work in notebooks)
        progress_tag=True,
        # To give a title to the progressbar
        progress_title="Sample",
    )   
    """
    for i in range(len(samples)):
        for w in range(len(samples[i])):
            samples[i][w] = int(samples[i][w]/10)

    for i in range(len(weights)):
        for w in range(len(weights[i])):
            weights[i][w] = int(weights[i][w]/10)
    """
    samples = samples[:4]
    labels = labels[:4]
    
    """ works with two parameters 
    winner_inputset =[([[160, 112, 16],[160, 160, 160]],samples), ([[160, 160, 160],[170, 170, 170]],samples),([[170, 170, 170],[150, 150, 150]],samples),([[150, 150, 150],[170, 170, 170]],samples),([[160,160, 160],[180, 150, 140]],samples),
                    ([[160, 112, 16],[160, 160, 160]],samples), ([[160, 160, 160],[170, 170, 170]],samples),([[170, 170, 170],[150, 150, 150]],samples),([[150, 150, 150],[170, 170, 170]],samples),([[160, 160, 160],[180, 150, 140]],samples)]
    """
    winner_inputset =[([[160, 112, 16],[160, 160, 160]],max(samples),0,5), ([[160, 160, 160],[170, 170, 170]],max(samples),1,8),([[170, 170, 170],[150, 150, 150]],max(samples),0,6),([[150, 150, 150],[170, 170, 170]],max(samples),0,5),([[160,160, 160],[180, 150, 140]],max(samples),0,6),
                    ([[160, 112, 16],[160, 160, 160]],min(samples),1,10), ([[160, 160, 160],[170, 170, 170]],min(samples),0,9),([[170, 170, 170],[150, 150, 150]],min(samples),1,7),([[150, 150, 150],[170, 170, 170]],min(samples),1,10),([[160, 160, 160],[180, 150, 140]],min(samples),1,9)]


    #inputset = [(inputset_weights,samples,labels,5),(inputset_weights,samples,labels,10)]
    #inputsetWithoutAlpa=[(inputset_weights,samples,labels),(inputset_weights,samples,labels)]
    print("Starte Kompillieren")
    lvqCircuit = lvqCompiler.compile(winner_inputset,configuration=configuration)
    #lvqCircuit = lvqCompiler.compile(winner_inputset)
    #lvqCircuit = lvqCompiler.compile(inputset)
    print("Kompillieren erfolgreich")
    lvqCircuit.keygen()

    """
    weights_enc, samples_enc, labels_enc , alpha_enc =lvqCircuit.encrypt(weights,samples,labels,5)
    new_weights = lvqCircuit.run(weights_enc,samples_enc,labels_enc,alpha_enc)
    """
    epochs = 1
    alpha = 5
    j =0
    samples_enc=[]
    labels_enc=[]
    for i in range(len(samples)):
        weights_enc, tmp,tmp2,alpha_enc =lvqCircuit.encrypt(weights,samples[i],labels[i],alpha)
        samples_enc.append(tmp)
        labels_enc.append(tmp2)

    weights_enc=lvqCircuit.run(weights_enc,samples_enc[j],labels_enc[j],alpha_enc)
    
    """
    print("Starte Iteration")
    
    for i in range(epochs):
        
        # for each sample
        for j in range(len(samples_enc)):
    """
        

Thx, forwarding this to the team