{"record":{"id":"ac6e44e91623fae7","repo":"xai-org/x-algorithm","slug":"unknown-loss-type-loss-type","errorCode":null,"errorMessage":"Unknown loss_type: {loss_type}","messagePattern":"Unknown loss_type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"phoenix/xrex/models/loss_recsys.py","lineNumber":88,"sourceCode":"\n    if mask_negatives:\n        loss_mask = valid_mask & (~negative_sample_mask)\n    else:\n        loss_mask = valid_mask\n\n    weights = loss_mask if raw_weights is None else loss_mask * raw_weights\n    num_loss_samples = jnp.sum(weights)\n\n    if loss_type == \"mse\":\n        errors = (pred_norm - gt_norm) ** 2\n    elif loss_type == \"mae\":\n        errors = jnp.abs(pred_norm - gt_norm)\n    elif loss_type == \"huber\":\n        delta = 1.0\n        abs_diff = jnp.abs(pred_norm - gt_norm)\n        errors = jnp.where(abs_diff <= delta, 0.5 * abs_diff**2, delta * (abs_diff - 0.5 * delta))\n    else:\n        raise ValueError(f\"Unknown loss_type: {loss_type}\")\n\n    loss = jnp.sum(errors * weights) / jnp.maximum(num_loss_samples, 1.0)\n\n    return loss, gt_clamped, pred_in_original_units, loss_mask, errors\n\n\ndef tweedie_loss_compute(\n    gt_raw: jax.Array,\n    pred_raw: jax.Array,\n    valid_mask: jax.Array,\n    negative_sample_mask: jax.Array,\n    p: float = 1.5,\n    norm_scale: float = 300.0,\n    mask_negatives: bool = True,\n    raw_weights: jax.Array | None = None,\n) -> tuple[jax.Array, jax.Array, jax.Array, jax.Array, jax.Array]:\n    gt = jnp.clip(gt_raw.astype(jnp.float32), 0.0, norm_scale)\n    pred = jnp.maximum(pred_raw.astype(jnp.float32), 1e-6)","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/phoenix/xrex/models/loss_recsys.py#L70-L106","documentation":"continuous_loss_compute supports a fixed set of loss_type strings for regression targets; the branches handle (per the source) absolute error and 'huber' (plus the preceding cases), and any other loss_type reaches the trailing ValueError. The loss is then normalized by num_loss_samples, so an unknown type cannot be silently defaulted.","triggerScenarios":"Calling loss()/continuous_loss_compute with loss_type like 'mse', 'l2', or a typo such as 'Huber' (case-sensitive) in the model config.","commonSituations":"Experiment configs renaming loss types; switching from another training framework whose loss names differ; case-sensitivity mistakes.","solutions":["Use one of the implemented loss_type values (check the if/elif arms in loss_recsys.py, e.g. 'huber').","Match exact casing/strings from the config schema.","Add a new elif branch implementing the loss if genuinely required."],"exampleFix":"# before\nloss_type: mse\n\n# after\nloss_type: huber","handlingStrategy":"validation","validationCode":"assert loss_type in {\"l1\", \"huber\"}, f\"Unknown loss_type: {loss_type}\"  # mirror implemented branches","typeGuard":"def is_supported_loss(t: str, supported: set[str]) -> bool:\n    return t in supported","tryCatchPattern":null,"preventionTips":["Validate loss_type against the branch list in loss_recsys.py at config parse time."],"tags":["loss","regression","enum-validation","config"],"backgroundTag":"invalid-config-value","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}