# APIUpdateConfig: How Ceres Handles Breaking Changes in Serialized Graphs

> Learn how Ceres APIUpdateConfig manages breaking changes in serialized graphs with its redirection tables for seamless node variable and assembly updates during deserialization.

- Repository: [AkiKurisu/ceres](https://github.com/akikurisu/ceres)
- Tags: internals
- Published: 2026-02-24

---

**APIUpdateConfig is a ScriptableObject that acts as a migration layer, using three redirector tables to automatically map outdated node types, variables, and assembly strings to their new counterparts during graph deserialization.**

The `APIUpdateConfig` class in the **akikurisu/ceres** repository solves the critical problem of backward compatibility when refactoring node classes, renaming namespaces, or restructuring assemblies. When you upgrade Ceres and encounter breaking changes in the public API, this configuration asset ensures existing serialized graphs load correctly without manual data migration or code changes.

## The Three Redirector Tables in APIUpdateConfig

At the core of `APIUpdateConfig` are three specialized redirector arrays defined in [`Runtime/Core/Models/Graph/APIUpdateConfig.cs`](https://github.com/akikurisu/ceres/blob/main/Runtime/Core/Models/Graph/APIUpdateConfig.cs)【^12-L73】. These tables store mapping rules that translate old serialized identities into current runtime types.

**Node redirectors** handle renamed or moved node classes. The array `Redirector<SerializedManagedReferenceType<CeresNode>>[] nodeRedirectors` maps obsolete node type definitions to their replacements using full assembly-qualified names.

**Variable redirectors** manage changes to shared variable implementations. The `Redirector<SerializedManagedReferenceType<SharedVariable>>[] variableRedirectors` array performs the same function for `SharedVariable` subclasses, ensuring blackboard variables survive refactoring.

**Assembly and namespace redirectors** solve string-level changes. The `Redirector<string>[]` entries rewrite assembly or namespace substrings embedded inside `SerializedType` strings, catching references that persist as text in serialized fields.

## Activation via ConfigAutoScope

Ceres activates the migration layer only during graph construction to minimize runtime overhead. The `APIUpdateConfig.AutoScope()` method creates a temporary `ConfigAutoScope` that sets the static `_activeConfig` field to the selected asset【^73-L94】.

When a graph builds, `CeresGraph` wraps deserialization in a `using (APIUpdateConfig.AutoScope())` block【^10-L17】. This scope automatically wires the `SerializedTypeRedirector.RedirectSerializedType` event if **auto-redirect** is enabled, then disposes after construction completes, resetting `_activeConfig` to null.

## Redirect Logic During Deserialization

The actual type resolution occurs inside `CeresGraphData` methods, which consult `APIUpdateConfig.Current` only when a config is active.

**Node restoration** follows this path: `RestoreNode` calls `APIUpdateConfig.Current.RedirectNodeType`, which iterates `nodeRedirectors` to find a matching source type and returns the new `System.Type` (or null if no match exists)【^72-L78】【^81-L86】.

**Variable restoration** mirrors the node pattern. `RestoreVariable` invokes `RedirectVariableType` to check `variableRedirectors` and substitute outdated variable classes before instantiation【^102-L108】.

**Serialized type strings** undergo substring rewriting. `RedirectSerializedType` uses the string redirectors to replace assembly or namespace fragments inside type identity strings【^118-L138】. `CeresGraphData.ResolveSerializedType` triggers this rewrite when the `enableAutoRedirectSerializedType` flag is active【^56-L64】.

## Safety Checks and Validation

All redirection calls are guarded by `Assert.IsTrue((bool)APIUpdateConfig.Current)` to ensure a valid configuration is active during deserialization【^24-L27】. This prevents silent null-reference failures if a developer forgets to assign the config asset, failing fast only in development builds while allowing production builds to skip the overhead entirely when no migration is needed.

## Workflow for Handling a Breaking Change

When a Ceres upgrade introduces incompatible type changes, follow this migration workflow:

1. **Create an APIUpdateConfig asset** via *Assets → Create → Ceres → API Update Config* (or use the editor script below).
2. **Populate redirect entries** in the Unity Inspector, mapping old assembly-qualified names to new ones.
3. **Enable auto-redirect** for string-based types by checking `enableAutoRedirectSerializedType` if namespace or assembly strings changed.
4. **Commit the asset** to version control so team members and CI builds automatically apply the same migration rules.

## Code Examples

### Creating an APIUpdateConfig Asset via Editor Script

Place this in an `Editor` folder to add a menu item for rapid config creation:

```csharp
using UnityEditor;
using Ceres.Graph;

public static class APIUpdateConfigCreator
{
    [MenuItem("Assets/Create/Ceres/API Update Config")]
    public static void Create()
    {
        var config = ScriptableObject.CreateInstance<APIUpdateConfig>();
        AssetDatabase.CreateAsset(config, "Assets/APIUpdateConfig.asset");
        AssetDatabase.SaveAssets();
        EditorUtility.FocusProjectWindow();
        Selection.activeObject = config;
    }
}

```

### Configuring Node Redirectors Programmatically

This example demonstrates the structure for remapping an obsolete node class to its replacement:

```csharp
var config = ScriptableObject.CreateInstance<APIUpdateConfig>();
config.nodeRedirectors = new[]
{
    new APIUpdateConfig.Redirector<APIUpdateConfig.SerializedManagedReferenceType<CeresNode>>
    {
        source = new APIUpdateConfig.SerializedManagedReferenceType<CeresNode>(
            new ManagedReferenceType("OldNamespace", "OldNodeName", "OldAssembly")),
        target = new APIUpdateConfig.SerializedManagedReferenceType<CeresNode>(
            new ManagedReferenceType("NewNamespace", "NewNodeName", "NewAssembly"))
    }
};
config.enableAutoRedirectSerializedType = true;

```

### Loading a Graph with Automatic Migration

No manual intervention is required when loading graphs; the scope is applied internally:

```csharp
// AutoScope is invoked automatically inside CeresGraph constructor
var graph = new CeresGraph(savedGraphData);

```

## Summary

- **APIUpdateConfig** is a ScriptableObject that stores migration rules for three categories: nodes, variables, and assembly/namespace strings.
- The **ConfigAutoScope** pattern ensures redirect logic is active only during deserialization, minimizing runtime performance impact.
- **RedirectNodeType**, **RedirectVariableType**, and **RedirectSerializedType** perform the actual type substitution in `CeresGraphData`.
- Safety assertions validate that a config is active before any redirection occurs, preventing silent failures.
- Breaking changes are resolved by creating and committing an APIUpdateConfig asset, allowing existing graph files to load seamlessly after refactoring.

## Frequently Asked Questions

### What happens if no APIUpdateConfig is assigned when loading an old graph?

If `APIUpdateConfig.Current` is null, the deserialization methods in `CeresGraphData` skip all redirection logic and attempt to instantiate types using their original serialized identities. This results in standard Unity serialization errors (missing scripts or null references) if the types no longer exist, but prevents silent data corruption by failing explicitly.

### Can I use multiple APIUpdateConfig assets for different graph collections?

Yes, you can create multiple assets, but only one can be active per deserialization scope. The `AutoScope()` method accepts an optional config parameter, allowing you to specify which migration rules apply when manually constructing specific graphs. For most projects, a single global config committed to version control is sufficient.

### Does APIUpdateConfig affect runtime performance after graph initialization?

No. Because `ConfigAutoScope` wraps only the construction phase and resets `_activeConfig` immediately after, the redirection lookup tables are not consulted during graph execution. The migration overhead is limited to the initial `new CeresGraph(data)` call, making this approach safe for production builds with frequent graph instantiation.

### How do I migrate types stored as strings in custom serialized fields?

Enable `enableAutoRedirectSerializedType` on your APIUpdateConfig asset and add entries to the string redirector table. The `RedirectSerializedType` method rewrites assembly and namespace substrings in `SerializedType` strings during `CeresGraphData.ResolveSerializedType`, catching edge cases where types are stored as text rather than managed references.