Find the dynamic contract
Start from the missing type or method and identify how it is reached. The managed-stripping guide describes supported preservation through attributes and link.xml.
Do not preserve every assembly before checking whether the library already provides the required annotations.
Preserve only the necessary surface
| Runtime behavior | Preservation question |
|---|---|
| Type loaded by name | Must the type and its name remain? |
| Reflective constructor | Which constructor is required? |
| Serialized member | Which fields/properties are accessed? |
| Generic AOT path | Is the needed instantiation available? |
The IL2CPP documentation provides context for AOT constraints. A rule fixing one reflective path does not establish compatibility for every generic or runtime-generated path.
Test the stripped release
Development or editor execution may not exercise the same stripping pipeline. Build the intended release backend and test the exact feature that failed.
Include less frequent content paths, downloaded content where supported and error recovery. A type used only in a later level can remain invisible to a short smoke test.
Keep preservation maintainable
Document why each attribute or XML entry exists and which test protects it. Review old broad rules during dependency upgrades rather than accumulating permanent keep-all exceptions.
A smaller output is not a success if the game fails to deserialize a saved session.
Inspect with appropriate limits
APKLint's Unity Analyzer can help identify packaged assemblies/native structures, but it cannot simulate the linker's complete reachability model or run reflective code. Retain the build's stripping settings, preservation file and release test evidence. The desired result is a narrow, explainable rule that preserves functionality while allowing unrelated unused code to be removed.
Investigate a type reached only from saved data
Suppose a release loads ordinary inventory items but fails when an older save contains a rare item class. In the editor, the same save works. Identify how the save library resolves that class and constructs it. If the type name comes from serialized data, a static reference search may not represent the runtime contract that the linker must preserve.
The managed stripping documentation describes supported preservation mechanisms. Consult the library's supplied annotations before adding your own rule. Record whether the missing surface is a type, a constructor, a field or a method; these require different preservation decisions and should not be replaced automatically with an assembly-wide exception.
Validate the rule against both missing and unused code
Build the original release profile with the smallest rule that covers the identified contract. Load the failing synthetic save, create another instance through the same dynamic path and save it again. Then load a save without that item to check the ordinary path. Test any supported migration from an older save format, since migration code can refer to types absent from newly created data.
If preservation does not solve the failure, inspect the actual exception and backend limitation. A required generic instantiation or unsupported runtime code generation can be a different problem from a stripped member. Repeatedly broadening a keep rule without confirming the failure mechanism can conceal the real compatibility issue and retain unnecessary code.
Keep each rule close to an explanation naming the feature and its regression fixture. When a dependency changes, repeat that fixture and review whether the library now supplies its own preservation metadata. A previously necessary rule can become redundant, but remove it only after testing the release pipeline that performs stripping.
Finally, compare output size and inspect build diagnostics where available. Treat size reduction as a secondary result after behavior is preserved. A short startup test cannot cover dynamically loaded content or every saved-data subtype, so document the fixture population rather than claiming exhaustive reachability proof. The strongest evidence is a previously failing release case that now works through a narrowly explained preservation change, alongside ordinary cases that remain functional under the intended backend and stripping level.
Sources and further reading
Reference review: 29 September 2026. Examples illustrate the workflow; check your installed versions, release artifact and account-specific Console requirements before applying them. This guide is not a claim that APKLint executed your project or verified your private account.


