{"record":{"id":"6ceaaa83f95c163e","repo":"stanfordnlp/CoreNLP","slug":"no-negative-parameters-allowed","errorCode":null,"errorMessage":"no negative parameters allowed!","messagePattern":"no negative parameters allowed!","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/stats/Multinomial.java","lineNumber":32,"sourceCode":"public class Multinomial<E> implements ProbabilityDistribution<E> {\n\n  /**\n   * \n   */\n  private static final long serialVersionUID = -697457414113362926L;\n  private Counter<E> parameters;\n\n  public Multinomial(Counter<E> parameters) {\n    double totalMass = parameters.totalCount();\n    if (totalMass <= 0.0) {\n      throw new RuntimeException(\"total mass must be positive!\");\n    }\n\n    this.parameters = new ClassicCounter<>();\n    for (E object : parameters.keySet()) {\n      double oldCount = parameters.getCount(object);\n      if (oldCount < 0.0) {\n        throw new RuntimeException(\"no negative parameters allowed!\");\n      }\n      this.parameters.setCount(object, oldCount/totalMass);\n    }\n  }\n\n  public Counter<E> getParameters() {\n    return new ClassicCounter<>(parameters);\n  }\n  \n  public double probabilityOf(E object) {\n    if (!parameters.keySet().contains(object)) {\n      throw new RuntimeException(\"Not a valid object for this multinomial!\");\n    }\n    return parameters.getCount(object);\n  }\n\n  public double logProbabilityOf(E object) {\n    if (!parameters.keySet().contains(object)) {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/stats/Multinomial.java#L14-L50","documentation":"After checking total mass is positive, the Multinomial constructor normalizes each count by the total; a negative individual count would yield a negative probability, so it throws. Probabilities in a multinomial must all be non-negative.","triggerScenarios":"new Multinomial(counter) where any key's getCount(object) < 0.0 — e.g. a counter used for gradient/weight deltas that accumulated negative values.","commonSituations":"Passing a counter that stores differences or log-ratios rather than raw counts; subtracting counts during online updates; float underflow bugs producing small negatives.","solutions":["Ensure all counts are non-negative before constructing (clamp negatives to 0 or reject the input)","Use the correct data structure — Multinomial expects counts, not signed scores","Inspect the counter contents to find which key has the negative value and fix the producer"],"exampleFix":"// before\nMultinomial<String> m = new Multinomial<>(deltaCounts);\n// after\ndeltaCounts.keySet().removeIf(k -> deltaCounts.getCount(k) < 0.0);\nMultinomial<String> m = new Multinomial<>(deltaCounts);","handlingStrategy":"validation","validationCode":"for (Object k : counter.keySet()) {\n  if (counter.getCount(k) < 0.0) throw new IllegalArgumentException(\"negative count for \" + k);\n}","typeGuard":"boolean hasNonNegativeCounts(Counter<?> c) {\n  return c.keySet().stream().allMatch(k -> c.getCount(k) >= 0.0);\n}","tryCatchPattern":"try {\n  return new Multinomial<>(counter);\n} catch (RuntimeException e) {\n  if (\"no negative parameters allowed!\".equals(e.getMessage())) {\n    counter.keySet().removeIf(k -> counter.getCount(k) < 0.0);\n    return new Multinomial<>(counter);\n  }\n  throw e;\n}","preventionTips":["Never feed delta/signed counters into Multinomial","Clamp negative values at accumulation time","Audit counters that get subtracted from"],"tags":["java","statistics","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}