# Plans for `id_root` and `target_id_type`
> [!Note]
> Skip down to the section entitled "The Plan" if you're already familiar with the issues around `id_root` and `target_id_type`.
## History / Context
### Animato
Animato Actions had an `id_root` property that specified what ID type their animation data was for. The `id_root` worked as follows:
- An Action could only (directly) be assigned to IDs of a type compatible with the type in its `id_root`. For example, `id_root == 'OBJECT'` could only be (directly) assigned to objects, not materials, etc.
- Action selectors in the UI only showed Actions with an `id_root` compatible with the current ID type.
- In addition to specfic types like 'OBJECT', `id_root` could also be set to 'UNSPECIFIED'.
- If 'UNSPECIFIED', the Action could be directly assigned to any animatible ID. However, when assigned, the `id_root` was then set to match the precise type of the ID it was assigned to.
- In addition to being changeable by assigning an `id_root == 'UNSPECIFIED'` Action to an ID, the `id_root` could also be directly set (regardless of current value) via the Python API.
The intent of the `id_root` was to prevent Actions from getting assigned to IDs they weren't suitable for. However, like many things in Animato, this supposed invariant was not actually enforceable due to how `id_root` worked. Specifically, because the `id_root` of an Action can be changed.
For example, here are two ways that you could end up with an Action assigned to an ID with an incompatible type:
- Direct `id_root` assignment:
1. Assign the Action to an object.
2. Via Python, set the Action's `id_root` to 'MATERIAL'.
3. Congratulations: a 'MATERIAL' Action is now assigned to an object.
- Library linking:
1. Create an `id_root == 'UNSPECIFIED'` action in blend file A via Python.
2. Link that Action into blend file B and assign it to an object. Since the Action is linked from another file, the `id_root` cannot be changed and remains 'UNSPECIFIED'.
3. Return to blend file A and assign the action to a material, causing its `id_root` to get updated to 'MATERIAL' to match.
4. Congratulations: in blend file B, you now have a 'MATERIAL' Action assigned to an object.
There are other ways this can be accomplished as well—these examples are not exhaustive.
The bottom line is that due to how it's designed, `id_root` cannot actually be depended on, and therefore is at best just for the user's convenience to filter out (probably) incompatible Actions in the Action selectors. It has no strong technical meaning.
### Slotted Actions
When we moved to slotted Actions, we adopted the concept of `id_root`, but moved it to the Action's Slots instead. Each Slot has a `target_id_type` property, which is their equivalent of `id_root`. Actions can now always be assigned to any animatible ID, but *Slots* can only be assigned to IDs matching the Slot's `target_id_type`.
For backwards compatibility with `id_root`, `target_id_type` has inherited most of the design decisions of `id_root`, including the 'UNSPECIFIED' value that changes upon assignment to an ID. This mean that, for the time being, `target_id_type` is also not reliable, and only serves as a strong hint for how a Slot is intended to be used.
This backwards compatibility is needed for two things:
1. For Python API backwards compatibility. The old `id_root` property now acts as a proxy for the first Slot's `target_id_type` so that old addons and scripts that rely on it continue to work. However, that means that `target_id_type` needs to match the old behavior of `id_root`.
2. To provide a good upgrade path for old Actions. When loading old Blend files, its Actions need to be converted to slotted Actions. This is done by creating a single Slot in the Action, with its `target_id_type` set the same as the Action's `id_root` was. We could remove 'UNSPECIFIED', and thus remove the "mutable" value, but that would force choosing e.g. 'OBJECT' for Slots created from old Actions that were `UNSPECIFIED`, which might make the animation data (directly) unassignable to the ID type it might have actually been intended for. This impacts both users and addons/scripts that might depend on that continuing to work.
These backwards compatibility concerns are important, and we believe these decisions are justified for the Blender 4.x series. However, it leaves `target_id_type` in an unfortunate state where, like `id_root` before it, it can change out from under you at any time and can't be relied on.
Additionally, *unlike* `id_root` before it, `target_id_type` affects the identifier of its Slot, so it's not just meta-data: changing it actually changes the string you use to look up a Slot. This makes the possibility of `target_id_type` changing out from under you (even just by assigning it to an ID!) even more of a mess than `id_root` was (which was already a mess).
We would like to eventually escape this mess, and bring some sanity to `target_id_type`. So we made a plan.
## The Plan
The goal is to eventually **make `target_id_type` immutable**: each Slot will be created with a specific value for `target_id_type`, and that value will never change after the Slot's creation.
This will make the value predictable and something that can be relied on. Moreover, outside of esoteric circumstances, it will prevent Slots from ending up assigned to IDs with an incompatible type.
> [!Note]
> We might even then be able to make it *actually* impossible for a Slot to end up assigned to an incompatible ID, with a little extra effort. Although that's a discussion for the future, and involves some further trade-offs that we might not want to make. But if we did so, it would then make `target_id_type` even *more* reliable and would give it a strong technical meaning.
To get there, we have a three-stage plan:
### Stage 1: Initial 4.4 Release, and Blender 4.x
The first release with slotted Actions (4.4) and the remainder of the 4.x series will work as follows:
- `id_root` is a proxy for the first Slot's `target_id_type` property.
- `id_root` can always be set to anything via Python, just like before, which makes `target_id_type` indirectly also always settable.
- `target_id_type` can only be *directly* set if it is currently 'UNSPECIFIED'. This matches the fact that `target_id_root` can be changed by assigning a Slot to an ID when it's 'UNSPECIFIED'. This limitation can of course be circumvented via the `id_root` shim, but it nevertheless sets the correct expectation for scripts that are using the slotted Action APIs.
- The API for creating new Slots requires a `target_id_type` to be specified with which to create the Slot (and does not permit `UNSPECIFIED` as an option). This means that `target_id_type == 'UNSPECIFIED'` Slots can only come into being through legacy Action upgrades or by setting the `id_root` shim.
The main theme of these releases is that the shim and backwards-compatible behaviors **give addon/script developers a window of time** where they can update their code to the new APIs at their leisure.
### Stage 2: Blender 5.x
In the 5.0 release, all the APIs around `target_id_root` will remain exactly the same, but **the `id_root` backwards compatibility shim will be removed entirely** (along with the other backwards compatibility shims).
This means that old addons/scripts that still haven't been updated to use the new APIs will break, and they will have to update.
`target_id_type` will still be settable when it's 'UNSPECIFIED', but due to the removal of the `id_root` shim the only possible source of 'UNSPECIFIED' Slots for the entire 5.x series will be loading old (4.x or earlier) files. Files created in 5.x will never have 'UNSPECIFIED' Slots.
This is how `target_id_type` will work for the entire 5.x series. **This makes `target_id_type` effectively immutable** for any files created by 5.x, but with an escape hatch for fixing up 'UNSPECIFIED' Slots from old files.
### Stage 3: Blender 6.x
In the 6.0 release, **`target_id_root` will be made fully immutable**.
We haven't yet decided how 'UNSPECIFIED' Slots from older files will be handled yet. Perhaps they'll be changed arbitrarily to 'OBJECT', or perhaps we'll just leave them alone and they can simply be assigned to anything (*without* their `target_id_root` changing). Heck, maybe we'll even bring back 'UNSPECIFIED' as a type of Slot you can create via the Python API, but now with the meaning "for storing arbitrary animation data not necessarily intended for an ID at all".
Who knows? This all still needs discussion.
But the main thing is that `target_id_root` will finally be completely immutable. 🥳