{"record":{"id":"ffb31420d58e0bb7","repo":"PaddlePaddle/PaddleOCR","slug":"the-mode-lower-if-kljsloss-should-be-one-of-kl","errorCode":null,"errorMessage":"The mode.lower() if KLJSLoss should be one of ['kl', 'js']","messagePattern":"The mode\\.lower\\(\\) if KLJSLoss should be one of \\['kl', 'js'\\]","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"ppocr/losses/basic_loss.py","lineNumber":81,"sourceCode":"            \"JS\",\n        ], \"mode can only be one of ['kl', 'KL', 'js', 'JS']\"\n        self.mode = mode\n\n    def __call__(self, p1, p2, reduction=\"mean\", eps=1e-5):\n        if self.mode.lower() == \"kl\":\n            loss = paddle.multiply(p2, paddle.log((p2 + eps) / (p1 + eps) + eps))\n            loss += paddle.multiply(p1, paddle.log((p1 + eps) / (p2 + eps) + eps))\n            loss *= 0.5\n        elif self.mode.lower() == \"js\":\n            loss = paddle.multiply(\n                p2, paddle.log((2 * p2 + eps) / (p1 + p2 + eps) + eps)\n            )\n            loss += paddle.multiply(\n                p1, paddle.log((2 * p1 + eps) / (p1 + p2 + eps) + eps)\n            )\n            loss *= 0.5\n        else:\n            raise ValueError(\n                \"The mode.lower() if KLJSLoss should be one of ['kl', 'js']\"\n            )\n\n        if reduction == \"mean\":\n            loss = paddle.mean(loss, axis=[1, 2])\n        elif reduction == \"none\" or reduction is None:\n            return loss\n        else:\n            loss = paddle.sum(loss, axis=[1, 2])\n\n        return loss\n\n\nclass DMLLoss(nn.Layer):\n    \"\"\"\n    DMLLoss\n    \"\"\"\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/ppocr/losses/basic_loss.py#L63-L99","documentation":"KLJSLoss implements only two divergence modes: 'kl' (symmetrized KL, first branch) and 'js' (Jensen-Shannon, second branch). The comparison is done on self.mode.lower(), so case is irrelevant, but any other string (e.g. 'JS ' with whitespace, 'kl_div', 'JSdiv') falls into the else and raises ValueError at forward time.","triggerScenarios":"Constructing KLJSLoss(mode='kd') or any string other than 'kl'/'js' (in any casing) and calling its forward; typical in distillation configs where mode is chosen per loss item.","commonSituations":"Typo in a distillation YAML (model_name/loss config under Loss for DistillationModel), copying a mode name from another framework ('kld', 'jsd'), or trailing whitespace in the config string.","solutions":["Set the loss mode to exactly 'kl' or 'js' (case-insensitive) in the config/constructor","Check the distillation config block that instantiates KLJSLoss and fix the mode key's value","Strip/normalize the string if it comes from user input: mode.strip().lower() before passing"],"exampleFix":"# before\nKLJSLoss(mode='jsd')   # ValueError at forward\n\n# after\nKLJSLoss(mode='js')","handlingStrategy":"validation","validationCode":"mode = mode.strip().lower()\nassert mode in ('kl', 'js'), f\"KLJSLoss mode must be 'kl' or 'js', got {mode!r}\"\nloss = KLJSLoss(mode=mode)","typeGuard":"def is_kljs_mode(m: str) -> bool:\n    return isinstance(m, str) and m.strip().lower() in ('kl', 'js')","tryCatchPattern":null,"preventionTips":["Validate loss-mode strings in your config loader against a whitelist per loss class","Linter/schema-validate YAML loss blocks (allowed values per loss name) before training","Remember comparison is case-insensitive but whitespace-sensitive"],"tags":["config","loss","distillation","enum-value"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}