{"record":{"id":"99a5dc19e21fbd0b","repo":"xai-org/x-algorithm","slug":"backward-block-sizes-block-q-dkv-block-kv-dkv-b","errorCode":null,"errorMessage":"Backward block sizes (block_q_dkv, block_kv_dkv, block_q_dq, block_kv_dq) must either all be specified or all be None.","messagePattern":"Backward block sizes \\(block_q_dkv, block_kv_dkv, block_q_dq, block_kv_dq\\) must either all be specified or all be None\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"phoenix/xrex/pallas/ranker_attention_fa3.py","lineNumber":68,"sourceCode":"    compute_wgs_bwd: int = 1\n\n    block_q_dkv: int | None = None\n    block_kv_dkv: int | None = None\n    block_q_dq: int | None = None\n    block_kv_dq: int | None = None\n\n    def __post_init__(self):\n        if self.block_q % 64:\n            raise ValueError(f\"{self.block_q=} must be a multiple of 64\")\n        if self.block_kv % 64:\n            raise ValueError(f\"{self.block_kv=} must be a multiple of 64\")\n        if self.max_concurrent_steps < 2:\n            raise ValueError(f\"{self.max_concurrent_steps=} must be at least 2\")\n\n        backward_blocks = [self.block_q_dkv, self.block_kv_dkv, self.block_q_dq, self.block_kv_dq]\n        block_is_set = [blk is not None for blk in backward_blocks]\n        if any(block_is_set) and not all(block_is_set):\n            raise ValueError(\n                \"Backward block sizes (block_q_dkv, block_kv_dkv, block_q_dq, \"\n                \"block_kv_dq) must either all be specified or all be None.\"\n            )\n\n    @property\n    def has_backward_blocks(self) -> bool:\n        return self.block_q_dkv is not None\n\n\ndef _attention_forward(\n    q,\n    k,\n    v,\n    config: TuningConfig,\n    save_residuals: bool = False,\n    bound=None,\n    sm_scale: float = 1.0,\n    cap: float = -1.0,","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/phoenix/xrex/pallas/ranker_attention_fa3.py#L50-L86","documentation":"TuningConfig allows overriding the four backward-pass tile sizes (block_q_dkv, block_kv_dkv, block_q_dq, block_kv_dq) only as a complete set. __post_init__ raises if some are set and others are None, to prevent half-configured backward kernels.","triggerScenarios":"Constructing TuningConfig with, e.g., block_q_dkv=128 but leaving block_kv_dkv/block_q_dq/block_kv_dq as None.","commonSituations":"Incrementally tuning only the dkv kernel's tiles; config files updated for some fields but not others after a version that added the dq overrides.","solutions":["Set all four backward block sizes explicitly","Or remove all backward block overrides to use defaults"],"exampleFix":"# before\ncfg = TuningConfig(..., block_q_dkv=128)\n# after\ncfg = TuningConfig(..., block_q_dkv=128, block_kv_dkv=64, block_q_dq=128, block_kv_dq=64)","handlingStrategy":"type-guard","validationCode":"null","typeGuard":"def has_all_backward_blocks(cfg) -> bool:\n    blocks = (cfg.block_q_dkv, cfg.block_kv_dkv, cfg.block_q_dq, cfg.block_kv_dq)\n    return all(b is None for b in blocks) or all(b is not None for b in blocks)","tryCatchPattern":null,"preventionTips":["Set backward blocks via one helper that takes all four values together","Assert cfg.has_backward_blocks before jax.grad calls"],"tags":["jax","pallas","tuning-config","backward-pass"],"backgroundTag":"all-or-nothing-config-fields","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}