xai-org/x-algorithm · error · ValueError

enable_candidate_tower_linear_proj and feature_prep_enabled

Error message

enable_candidate_tower_linear_proj and feature_prep_enabled (candidate project-then-sum) are mutually exclusive; enable at most one (or neither for mean-pool on the candidate tower).

What it means

The two-tower xrecsys config validator rejects any ModelParams that enables both enable_candidate_tower_linear_proj and feature_prep_enabled. Both flags select a (mutually exclusive) reduction strategy for the candidate tower embeddings (linear projection vs project-then-sum feature prep), so enabling both makes the intended architecture ambiguous. The check deliberately runs before the emb_size % 128 assertion so misconfiguration fails fast at config-parse time rather than mid-training.

Source

Thrown at phoenix/xrex/configs/xrecsys_two_tower.py:517

    use_user_features = _has_user_features_token(mparams)

    dataset = _make_dataset(mparams, dataset_type, hash_table, config_name)
    evals = []
    for _build_evals in config_registry.RETRIEVAL_EVAL_BUILDERS:
        evals += _build_evals(mparams, dataset, _has_user_features_token)

    raw_checkpoint_datasets = mparams.get("checkpoint_dataset_names", None)
    if isinstance(raw_checkpoint_datasets, str):
        checkpoint_dataset_names = [
            s.strip() for s in raw_checkpoint_datasets.split(",") if s.strip()
        ]
    else:
        checkpoint_dataset_names = raw_checkpoint_datasets

    if mparams.get("enable_candidate_tower_linear_proj") and mparams.get(
        "feature_prep_enabled", False
    ):
        raise ValueError(
            "enable_candidate_tower_linear_proj and feature_prep_enabled "
            "(candidate project-then-sum) are mutually exclusive; enable at most one "
            "(or neither for mean-pool on the candidate tower)."
        )

    assert mparams["emb_size"] % 128 == 0
    assert mparams["emb_table_width"] % 128 == 0
    hl = mparams["history_seq_len"]
    use_user_embedding = mparams.get("use_user_embedding", True)
    scale_config = _default_recsys_scaling()
    num_user_prefix_tokens = _num_user_prefix_tokens(mparams, use_user_embedding, scale_config)
    total_seq = num_user_prefix_tokens + hl
    use_seqpack = mparams.get("use_seqpack", False)

    if num_user_prefix_tokens > 1:
        assert (total_seq & (total_seq - 1)) == 0, (
            f"total sequence length ({total_seq} = {num_user_prefix_tokens} + {hl}) must be a power of 2"
        )

View on GitHub (pinned to 24c60942c5)

Solutions

  1. If you want a projection on the candidate tower, keep enable_candidate_tower_linear_proj=True and set feature_prep_enabled=False.
  2. If you want project-then-sum feature prep, set feature_prep_enabled=True and remove/False enable_candidate_tower_linear_proj.
  3. If you want neither (mean-pooling on the candidate tower), set both flags to False.
  4. Audit your YAML/CLI override chain to find where feature_prep_enabled gets enabled globally and scope it correctly.

Example fix

# before
mparams = dict(
    enable_candidate_tower_linear_proj=True,
    feature_prep_enabled=True,
)

# after (project-then-sum prep on candidate tower)
mparams = dict(
    enable_candidate_tower_linear_proj=False,
    feature_prep_enabled=True,
)
Defensive patterns

Strategy: validation

Validate before calling

def validate_two_tower_mparams(mparams):
    if mparams.get("enable_candidate_tower_linear_proj") and mparams.get(
        "feature_prep_enabled", False
    ):
        raise ValueError(
            "pick one candidate-tower reduction: "
            "enable_candidate_tower_linear_proj OR feature_prep_enabled (or neither)"
        )

validate_two_tower_mparams(mparams)  # before building the trainer

Type guard

def has_valid_candidate_tower_flags(m) -> bool:
    return not (m.get("enable_candidate_tower_linear_proj") and m.get("feature_prep_enabled", False))

Prevention

When it happens

Trigger: Setting both mparams['enable_candidate_tower_linear_proj']=True and mparams['feature_prep_enabled']=True in the two-tower config (or via CLI overrides / YAML merge that turns on feature prep globally while the model flags linear proj).

Common situations: Copy-pasting a candidate-tower config that uses linear projection into a pipeline config where feature_prep_enabled is already on; flipping feature_prep_enabled for the query tower and forgetting it also affects the candidate tower; defaults changing between config versions so an old flag now conflicts.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/f107127063b199d3. Report an issue: GitHub.