{"record":{"id":"15a91f01782f7cd1","repo":"huggingface/transformers","slug":"key-is-a-per-layer-attribute-and-may-vary-acro","errorCode":null,"errorMessage":"'{key}' is a per-layer attribute and may vary across layers. Access it via the individual layer configs instead (e.g. config.per_layer_config[i].{key}). To read the global config value from config.{key} anyway, set `allow_global_per_layer_attribute_access` to `True` on the config. Warning: only do this if the caller can safely handle heterogeneous configs; code that assumes a homogeneous model may use the global value incorrectly.","messagePattern":"'(.+?)' is a per-layer attribute and may vary across layers\\. Access it via the individual layer configs instead \\(e\\.g\\. config\\.per_layer_config\\[i\\]\\.(.+?)\\)\\. To read the global config value from config\\.(.+?) anyway, set `allow_global_per_layer_attribute_access` to `True` on the config\\. Warning: only do this if the caller can safely handle heterogeneous configs; code that assumes a homogeneous model may use the global value incorrectly\\.","errorType":"validation","errorClass":"AmbiguousGlobalPerLayerAttributeError","httpStatus":null,"severity":"error","filePath":"src/transformers/integrations/heterogeneity/configuration_utils.py","lineNumber":298,"sourceCode":"    return explicit_per_layer_overrides\n\n\nclass HeterogeneousConfigMixin:\n    \"\"\"Mixin for heterogeneous per-layer config behavior.\n\n    This mixin owns heterogeneity-specific state and rules. ``PreTrainedConfig`` assigns the ``per_layer_config``\n    property in the post-init phase and calls hook methods where heterogeneity needs to participate in the config lifecycle: attribute\n    access, key iteration, and serialization.\n    \"\"\"\n\n    def __getattribute__(self, key: str) -> Any:\n        # In heterogeneous configs, per-layer attributes are ambiguous on the global config.\n        # Callers must read them from a concrete layer unless they explicitly opt into the global value.\n        heterogeneity_spec = super().__getattribute__(\"__dict__\").get(\"_heterogeneity_spec\")\n        if heterogeneity_spec is not None:\n            if key in heterogeneity_spec.per_layer_attributes:\n                if not super().__getattribute__(\"allow_global_per_layer_attribute_access\"):\n                    raise AmbiguousGlobalPerLayerAttributeError(\n                        f\"'{key}' is a per-layer attribute and may vary across layers. Access it via the individual layer \"\n                        f\"configs instead (e.g. config.per_layer_config[i].{key}). To read the global config value from \"\n                        f\"config.{key} anyway, set `allow_global_per_layer_attribute_access` to `True` on the config. \"\n                        f\"Warning: only do this if the caller can safely handle heterogeneous configs; code that assumes \"\n                        f\"a homogeneous model may use the global value incorrectly.\"\n                    )\n\n                logger.warning_once(\n                    f\"Reading global config value for per-layer attribute `{key}` on a heterogeneous config. \"\n                    \"Only do this if the caller can safely handle heterogeneous configs; code that assumes a homogeneous \"\n                    \"model may use the global value incorrectly.\"\n                )\n\n        return super().__getattribute__(key)\n\n    @property\n    def is_heterogeneous(self) -> bool:\n        return hasattr(self, \"_heterogeneity_spec\")","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/huggingface/transformers/blob/a597f974857b3d92939971296bc0deb93d33d780/src/transformers/integrations/heterogeneity/configuration_utils.py#L280-L316","documentation":"On a heterogeneous config, attributes listed in `_heterogeneity_spec.per_layer_attributes` (e.g. `num_key_value_heads`) may differ per layer, so reading them from the global config is ambiguous. The `__getattribute__` hook in the heterogeneity mixin raises `AmbiguousGlobalPerLayerAttributeError` unless the config flag `allow_global_per_layer_attribute_access` is explicitly set to True, in which case it only warns. This forces callers to either read a concrete layer config or consciously opt into the (possibly wrong) global value.","triggerScenarios":"Reading `config.num_key_value_heads` (any name registered as a per-layer attribute) on a config with a `_heterogeneity_spec` whose `per_layer_attributes` contains that key, while `config.allow_global_per_layer_attribute_access` is False (default). Triggers anywhere: user scripts, generic modeling code, `AutoModel` plumbing that introspects config attributes.","commonSituations":"Third-party or user code written for homogeneous models that assumes `config.<attr>` is authoritative; heterogeneous checkpoints (mixed GQA heads, mixed rope settings per layer) loaded through generic utils that read config attributes; serialization/inspection tooling that walks all config attributes.","solutions":["Read the value from a concrete layer: `config.per_layer_config[i].num_key_value_heads`.","If your code genuinely handles heterogeneous models, opt in globally on that config instance: `config.allow_global_per_layer_attribute_access = True` (expect a `logger.warning_once`).","Update generic introspection code to check `getattr(config, \"_heterogeneity_spec\", None) is not None` before touching potentially per-layer attributes."],"exampleFix":"# before\nkv_heads = config.num_key_value_heads  # AmbiguousGlobalPerLayerAttributeError\n\n# after\nkv_heads = config.per_layer_config[0].num_key_value_heads\n\n# or, only if the caller handles heterogeneity safely:\nconfig.allow_global_per_layer_attribute_access = True\nkv_heads = config.num_key_value_heads","handlingStrategy":"validation","validationCode":"spec = getattr(config, \"_heterogeneity_spec\", None)\nif spec is not None and key in spec.per_layer_attributes:\n    value = config.per_layer_config[0].__getattribute__(key)  # read from a concrete layer\nelse:\n    value = getattr(config, key)","typeGuard":"def is_per_layer_attribute(config, key: str) -> bool:\n    spec = getattr(config, \"_heterogeneity_spec\", None)\n    return spec is not None and key in spec.per_layer_attributes","tryCatchPattern":"from transformers.integrations.heterogeneity.configuration_utils import AmbiguousGlobalPerLayerAttributeError\n\ntry:\n    v = getattr(config, key)\nexcept AmbiguousGlobalPerLayerAttributeError:\n    v = getattr(config.per_layer_config[0], key)","preventionTips":["In generic config-introspection code, check _heterogeneity_spec before touching attributes.","Prefer per_layer_config[i] as the source of truth for structural attributes on heterogeneous models.","Only set allow_global_per_layer_attribute_access in code paths proven to handle layer-varying values."],"tags":["config","heterogeneity","attribute-access","ambiguity"],"backgroundTag":null,"analyzedSha":"a597f974857b3d92939971296bc0deb93d33d780","analyzedAt":"2026-08-14T18:24:08.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}