{"record":{"id":"5b7322508e8d81c9","repo":"TheAlgorithms/Java","slug":"classifier-has-not-been-fitted","errorCode":null,"errorMessage":"classifier has not been fitted","messagePattern":"classifier has not been fitted","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/thealgorithms/machinelearning/MultinomialNaiveBayesClassifier.java","lineNumber":106,"sourceCode":"\n            double denom = total + alpha * numFeatures;\n            double[] logLikelihood = new double[numFeatures];\n            for (int j = 0; j < numFeatures; j++) {\n                logLikelihood[j] = Math.log((sums[j] + alpha) / denom);\n            }\n            logLikelihoods.put(label, logLikelihood);\n        }\n    }\n\n    /**\n     * Predicts the most likely class for a single sample.\n     *\n     * @param sample feature vector of non-negative counts\n     * @return the predicted class label\n     */\n    public int predict(double[] sample) {\n        if (logPriors.isEmpty()) {\n            throw new IllegalStateException(\"classifier has not been fitted\");\n        }\n        if (sample.length != numFeatures) {\n            throw new IllegalArgumentException(\"sample length must match training feature count\");\n        }\n\n        int bestLabel = -1;\n        double bestScore = Double.NEGATIVE_INFINITY;\n\n        for (Map.Entry<Integer, double[]> entry : logLikelihoods.entrySet()) {\n            int label = entry.getKey();\n            double[] logLikelihood = entry.getValue();\n            double score = logPriors.getOrDefault(label, Double.NEGATIVE_INFINITY);\n            for (int j = 0; j < numFeatures; j++) {\n                score += sample[j] * logLikelihood[j];\n            }\n            if (score > bestScore) {\n                bestScore = score;\n                bestLabel = label;","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/TheAlgorithms/Java/blob/fdfb9a395b310167a66bd29e311e36e0e3e9b964/src/main/java/com/thealgorithms/machinelearning/MultinomialNaiveBayesClassifier.java#L88-L124","documentation":"MultinomialNaiveBayesClassifier.predict throws IllegalStateException (unchecked) when logPriors is empty, which is the state after construction but before fit() is called. predict relies on fitted log-priors and log-likelihoods; with none, there is no model to evaluate. This is a lifecycle/state error, not an argument error.","triggerScenarios":"Calling predict(sample) on a classifier instance that was never fit — i.e. new MultinomialNaiveBayesClassifier() followed directly by predict without an intervening fit().","commonSituations":"Forgetting to call fit in a training/serving pipeline, a model-loading routine that failed silently and left the classifier unfitted, or unit tests that construct and predict without training.","solutions":["Always call fit(features, labels) before any predict call.","If the model is optional, track a fitted flag and skip prediction when not fitted.","When loading a pre-trained model, rehydrate the priors/likelihoods or re-fit, rather than predicting on a fresh instance."],"exampleFix":"// before\nvar clf = new MultinomialNaiveBayesClassifier();\nint label = clf.predict(sample); // not fitted\n\n// after\nvar clf = new MultinomialNaiveBayesClassifier();\nclf.fit(trainFeatures, trainLabels);\nint label = clf.predict(sample);","handlingStrategy":"validation","validationCode":"if (!isFitted) {\n    throw new IllegalStateException(\"classifier not fitted; call fit first\");\n}\nclassifier.predict(sample);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call fit before predict; make this explicit in your training/serving pipeline.","Track a fitted flag in your wrapper so you can short-circuit predict gracefully.","When loading a model, rehydrate fitted state or re-fit rather than predicting on a fresh instance."],"tags":["machine-learning","lifecycle","state-error","not-fitted","naive-bayes","illegal-state"],"backgroundTag":null,"analyzedSha":"fdfb9a395b310167a66bd29e311e36e0e3e9b964","analyzedAt":"2026-08-13T23:36:13.315Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}