{"record":{"id":"4e97fc46bdea60b4","repo":"xai-org/x-algorithm","slug":"metric-mask-keys-entries-sorted-unknown-not-in","errorCode":null,"errorMessage":"metric_mask_keys entries {sorted(unknown)} not in available masks {sorted(masks)}","messagePattern":"metric_mask_keys entries (.+?) not in available masks (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"phoenix/xrex/models/recsys_model.py","lineNumber":1405,"sourceCode":"\n    if condition_search_relevance_on_prompt:\n        prompt_mask = jnp.any(\n            raw_targets[:, :, jnp.array(SEARCH_RELEVANCE_ACTION_INDICES)] == 1, axis=-1\n        ).astype(mask.dtype)\n        masks[\"prompted\"] = mask * prompt_mask\n        masks[\"non_negative_prompted\"] = non_negative_mask * prompt_mask\n\n    if enable_platform_metrics and ios_mask is not None and android_mask is not None:\n        masks[\"ios\"] = ios_mask\n        masks[\"android\"] = android_mask\n        masks[\"ios_non_negative\"] = ios_mask * (1 - negative_sample_mask)\n        masks[\"android_non_negative\"] = android_mask * (1 - negative_sample_mask)\n\n    if metric_mask_keys:\n        keep = set(metric_mask_keys)\n        unknown = keep - masks.keys()\n        if unknown:\n            raise ValueError(\n                f\"metric_mask_keys entries {sorted(unknown)} not in available masks {sorted(masks)}\"\n            )\n        masks = {k: v for k, v in masks.items() if k in keep}\n\n    return masks\n\n\n@dataclass\nclass RecsysAggregatedModel(hk.Module):\n    config: RecsysAggregatedModelConfig\n    model: Transformer\n    sharding_context: ShardingContext\n\n    @property\n    def data_axis(self):\n        return (\"stage\", *self.config.model_config.data_axis)\n\n    def _compute_metrics_after_masks(","sourceCodeStart":1387,"sourceCodeEnd":1423,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/phoenix/xrex/models/recsys_model.py#L1387-L1423","documentation":"build_metric_masks constructs a fixed dictionary of evaluation masks (e.g. android_mask, negative-sample-complement 'android_non_negative', etc.). When metric_mask_keys is provided it is treated as a keep-filter, and any key not present in the built masks is reported with both the unknown keys and the full list of available masks.","triggerScenarios":"Passing metric_mask_keys=[\"ios_non_negative\", \"android\"] when only the built mask names exist; referencing a mask removed in a refactor during init, checkpoint finalization, or _build_metric_masks.","commonSituations":"Configs referencing masks from an older version; renaming of mask keys; typos in key lists.","solutions":["Use only mask names from the 'available masks' list printed in the error.","Remove stale keys from metric_mask_keys after mask renames/removals.","If a mask is genuinely missing (e.g. an ios counterpart), add its computation in build_metric_masks."],"exampleFix":"# before\nmetric_mask_keys: [\"ios_non_negative\", \"android_non_negative\"]\n\n# after\nmetric_mask_keys: [\"android_non_negative\"]","handlingStrategy":"validation","validationCode":"from phoenix.xrex.models.recsys_model import build_metric_masks  # dry-run to enumerate masks\navailable = set(build_metric_masks(batch, metric_mask_keys=[]))\nunknown = set(metric_mask_keys) - available\nassert not unknown, f\"unknown mask keys: {sorted(unknown)}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Dry-run build_metric_masks with an empty keep-list to enumerate valid keys at startup.","Add a config lint for metric_mask_keys after mask renames."],"tags":["metrics","mask-validation","config","recsys"],"backgroundTag":"unknown-config-key","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}