Misleading Exception Messages in CKKS (with ScalingTechnique & ScalingModSize)

Hello,

Through my previous reports, I understand that you’re working toward addressing invalid context issues more systematically via AAHE in OpenFHE. That said, I’d like to share a couple of misleading exception cases I recently encountered (both in CKKS). I realize these may not be immediate concerns, but I thought they might be useful to flag as you continue refining error handling scenarios.

1. Exception under FLEXIBLEAUTO scaling technique masks true invalidity

When using CKKS with SetScalingTechnique(FLEXIBLEAUTO) in some invalid contexts, the library throws the following exception:

FLEXIBLEAUTO cannot support this number of levels in this parameter setting. Please use FIXEDMANUAL or FIXEDAUTO instead.

However, switching to FIXEDMANUAL or FIXEDAUTO doesn’t actually solve the problem — instead, the real underlying invalidity is revealed via a more accurate error message. This suggests that the original exception is not describing the core problem, but rather redirecting the user elsewhere.

Here are some specific examples of invalid contexts where this occurs (I’ll attach a concrete code example only for the first case later, since others’ code is too long) :

  • Using insufficient multiplicative depth.
  • Setting the length greater than a half of the ring dimension.
  • Setting the bound for elements greater than 2 to the power of firstModSize.

In these situations, FLEXIBLEAUTO fails early with a generic suggestion to “just switch techniques”, while the actual problem is deeper and relevant regardless of scaling method.

It would be more helpful if the library could expose the true issue even when FLEXIBLEAUTO is used — either by surfacing the same underlying exception or by chaining both messages.

Code Example: Using insufficient multiplicative depth (v1.2.4)

int main(void) {
  CCParams<CryptoContextCKKSRNS> parameters;
  parameters.SetRingDim(16384);
  parameters.SetMultiplicativeDepth(2);
  parameters.SetFirstModSize(20);
  parameters.SetScalingModSize(19);
  parameters.SetSecurityLevel(HEStd_256_classic);
  parameters.SetScalingTechnique(FLEXIBLEAUTO);
  
  CryptoContext<DCRTPoly> cc = GenCryptoContext(parameters);
  cc->Enable(PKE);
  cc->Enable(KEYSWITCH);
  cc->Enable(LEVELEDSHE);
  KeyPair<DCRTPoly> keyPair;
  keyPair = cc->KeyGen();
  cc->EvalMultKeyGen(keyPair.secretKey);
  size_t slots(2094);
  vector<complex<double>> tmp_vec_(2094);
  Plaintext tmp;
  Ciphertext<DCRTPoly> tmp_;

  Ciphertext<DCRTPoly> x, y;
  double yP;
  vector<double> tmp_vec_1 = { 91251.113286 };
  tmp = cc->MakeCKKSPackedPlaintext(tmp_vec_1);
  x = cc->Encrypt(keyPair.publicKey, tmp);
  vector<double> tmp_vec_2 = { 1.000000 };
  tmp = cc->MakeCKKSPackedPlaintext(tmp_vec_2);
  y = cc->Encrypt(keyPair.publicKey, tmp);
  x = cc->EvalMultNoRelin(x, y);
  cc->RescaleInPlace(x);
  cc->RelinearizeInPlace(x);
  yP = 1.000000;
  vector<double> tmp_vec_3(slots, yP);
  tmp = cc->MakeCKKSPackedPlaintext(tmp_vec_3);
  x = cc->EvalMult(x, tmp);
  cc->RescaleInPlace(x);
  vector<double> tmp_vec_4 = { 1.000000 };
  tmp = cc->MakeCKKSPackedPlaintext(tmp_vec_4);
  y = cc->Encrypt(keyPair.publicKey, tmp);
  x = cc->EvalMultNoRelin(x, y);
  cc->RescaleInPlace(x);
  cc->RelinearizeInPlace(x);
  cc->Decrypt(keyPair.secretKey, x, &tmp);
  tmp->SetLength(5);
  tmp_vec_ = tmp->GetCKKSPackedValue();
  for (int64_t tmp_i = 0; tmp_i < 5; ++tmp_i) {
    cout << fixed << setprecision(5) << real(tmp_vec_[tmp_i]) << " ";
  }
  cout << endl;
  return 0;
}
  • Exception message after changing the scaling technique into FIXEDMANUAL or FIXEDAUTO:

    Removing last element of DCRTPoly renders it invalid

    • This is a more appropriate message (e.g., indicating invalidity of the context), since the multiplicative depth is set as 2, smaller than the actual number of multiplication, 3.

2. Incorrect message for negative scalingModSize

This one is minor, but I think it’s worth pointing out at least briefly. If the user sets scalingModSize < 0, the exception message is:

“scalingModSize should be less than 60”

This message is technically incorrect — the problem is that the input is too small, not too large. I assume internally the negative value is being interpreted as a large unsigned integer, which causes the wrong error to be triggered.

For comparison, BFV in the same case throws:

“Number of bits in CRT moduli should be in the range from 30 to 60”

— which more accurately communicates the valid range.

It would be great if CKKS could provide a similarly informative error message here to help users quickly spot input mistakes.

__
Thanks again for your continued support!

Thank you for reporting these. We will revise the exception handling messages as part of the changes for Improve exception handling for selected scenarios leading to incorrect results · Issue #995 · openfheorg/openfhe-development · GitHub