find-refs was previously marked experimental and it shows: the semantics are under-documented, the output is ambiguous in common cases, and there are a couple of real bugs. This issue covers clarifying the semantics (docs), fixing output/error behavior, and adding tests to pin down the assumptions. Findings below are from reading ReferenceFinderTool.cs and testing against the v2.1.0 binary.
How it works today (code-confirmed)
The tool walks up the reference graph from the target via refs_view. A chain is only reported when the walk reaches an object that is "explicitly included" in the build, meaning either:
- a row in
assetbundle_assets — an asset explicitly added to an AssetBundle at build time (its m_Container), or
- a loadable object from an imported ContentLayout (
content_layout_loadable_objects_view), for ContentDirectory builds.
The walk stops at the first such object (documented in command-find-refs.md). Referencing objects that never lead up to an explicitly-included object are dropped and no chain is reported.
Terminology needs care
referencefinder.md calls the chain endpoint a "root asset". That term has a specific meaning in the content directory context, and here it is being used for the AssetBundle m_Container concept — while for ContentDirectory builds the endpoints are actually Loadables. The docs (and any new output messages) should settle on precise terms per build type instead of one overloaded "root asset".
Confirmed problems
1. Found 0 reference chain(s) is ambiguous. At least three very different situations produce the identical output, with no hint which one applies:
- The target is itself explicitly included (AssetBundle asset / Loadable) and nothing else references it. This is normal, not an error — explicitly-added assets are loadable and belong in the build with no referencing object. Verified: a texture that is an explicit bundle asset reports 0 chains; in an agent-usability experiment this single case cost more effort than everything else combined (the agent had to query
refs by hand, fetch two doc pages, and re-run against a different object to rule out a tool bug).
- The target is genuinely unreferenced / unreachable from any explicitly-included object.
- The database structurally cannot produce chains at all. Verified: a Player-build database has no
assetbundle_assets rows and no loadables, so find-refs on a Player build always reports 0 chains (with a healthy, fully-populated refs table). Nothing in the docs or output says so.
The output should distinguish these (e.g. state when the target is itself an explicitly-included asset/loadable, and when the database contains no chain endpoints at all).
2. State leaks across multiple matched objects. m_Roots and m_ProcessedObjects are member fields and are never reset between the objects matched by -n. Verified with a name matching two objects (same shader in two archives): the second section re-prints the first object's chains under the second object's header, and "Found N reference chain(s)" accumulates. Chain output for anything but the first matched object is unreliable. (The existing multi-match test only asserts that both type headers appear, so it doesn't catch this.)
3. -i with a nonexistent id crashes with an unhandled-exception stack trace (reader.Read() return value unchecked before GetString when printing the target header). Should be a clear "no object with id N" message like the -n path's "No object found!".
4. The empty-refs message points at only one cause. "Database 'refs' table empty! Make sure to not use the --skip-references option" — but an analyze run that processed 0 files also produces an empty refs table, and an agent following the message literally goes hunting for a flag that was never used. Enumerate both causes.
5. Message plumbing. Error messages are written with Console.WriteLine (stdout); the other commands put errors on stderr. Worth aligning while in here. Exit codes are mostly sensible (1 for no-object/empty-refs/bad-db); 0 chains found should remain exit 0 since it is often a normal answer.
Docs
Beyond fixing terminology, spell out the semantics with worked examples, since this is the least-understood command:
- a reference chain within a single prefab (GameObject/Component hierarchy, the existing example);
- references between separate assets in the same bundle;
- references spanning AssetBundles (chain endpoint in one bundle, target in another) — confirm and document that this works when both bundles are in the same database;
- per-build-type behavior: AssetBundles (endpoints = explicitly added assets), ContentDirectory (endpoints = Loadables; requires ContentLayout.json in the analyze input; clarify what is and isn't visible, e.g. an object referenced by a Loadable is in the build but consumers of the Loadable itself won't appear), Player builds (currently: no endpoints exist, so no chains ever — either document as a limitation or define what the endpoints should be, e.g. scenes);
- the duplicated-asset use case (
-n matching multiple ids) — once bug 2 is fixed;
- update
referencefinder.md, which still describes an AssetBundle-only "root asset" model and predates the loadable support.
Tests
FindRefsTests.cs has decent happy-path coverage (LeadingEdge bundles, chain shapes, stop-at-first-asset, schema-version and empty-refs errors). Add:
- multi-match
-n asserting per-section chain counts (pins the bug 2 fix);
-i with a nonexistent id (pins the bug 3 fix);
- target-is-explicitly-included-asset reporting whatever new message is chosen (bug 1);
- a Player-build database (whatever behavior is decided);
- a cross-bundle chain;
- a ContentDirectory/Loadable chain beyond the single one in AnalyzeContentLayoutTests.
Open questions
- What should chain endpoints be for Player builds, if anything (scenes / preload tables / Resources)?
- Exact wording and terminology per build type for the new output messages.
- Whether
find-refs should proactively note when the target is in assetbundle_assets even when chains are found (it is useful context either way).
find-refswas previously marked experimental and it shows: the semantics are under-documented, the output is ambiguous in common cases, and there are a couple of real bugs. This issue covers clarifying the semantics (docs), fixing output/error behavior, and adding tests to pin down the assumptions. Findings below are from readingReferenceFinderTool.csand testing against the v2.1.0 binary.How it works today (code-confirmed)
The tool walks up the reference graph from the target via
refs_view. A chain is only reported when the walk reaches an object that is "explicitly included" in the build, meaning either:assetbundle_assets— an asset explicitly added to an AssetBundle at build time (itsm_Container), orcontent_layout_loadable_objects_view), for ContentDirectory builds.The walk stops at the first such object (documented in command-find-refs.md). Referencing objects that never lead up to an explicitly-included object are dropped and no chain is reported.
Terminology needs care
referencefinder.mdcalls the chain endpoint a "root asset". That term has a specific meaning in the content directory context, and here it is being used for the AssetBundlem_Containerconcept — while for ContentDirectory builds the endpoints are actually Loadables. The docs (and any new output messages) should settle on precise terms per build type instead of one overloaded "root asset".Confirmed problems
1.
Found 0 reference chain(s)is ambiguous. At least three very different situations produce the identical output, with no hint which one applies:refsby hand, fetch two doc pages, and re-run against a different object to rule out a tool bug).assetbundle_assetsrows and no loadables, so find-refs on a Player build always reports 0 chains (with a healthy, fully-populatedrefstable). Nothing in the docs or output says so.The output should distinguish these (e.g. state when the target is itself an explicitly-included asset/loadable, and when the database contains no chain endpoints at all).
2. State leaks across multiple matched objects.
m_Rootsandm_ProcessedObjectsare member fields and are never reset between the objects matched by-n. Verified with a name matching two objects (same shader in two archives): the second section re-prints the first object's chains under the second object's header, and "Found N reference chain(s)" accumulates. Chain output for anything but the first matched object is unreliable. (The existing multi-match test only asserts that both type headers appear, so it doesn't catch this.)3.
-iwith a nonexistent id crashes with an unhandled-exception stack trace (reader.Read()return value unchecked beforeGetStringwhen printing the target header). Should be a clear "no object with id N" message like the-npath's "No object found!".4. The empty-refs message points at only one cause. "Database 'refs' table empty! Make sure to not use the --skip-references option" — but an analyze run that processed 0 files also produces an empty refs table, and an agent following the message literally goes hunting for a flag that was never used. Enumerate both causes.
5. Message plumbing. Error messages are written with
Console.WriteLine(stdout); the other commands put errors on stderr. Worth aligning while in here. Exit codes are mostly sensible (1 for no-object/empty-refs/bad-db); 0 chains found should remain exit 0 since it is often a normal answer.Docs
Beyond fixing terminology, spell out the semantics with worked examples, since this is the least-understood command:
-nmatching multiple ids) — once bug 2 is fixed;referencefinder.md, which still describes an AssetBundle-only "root asset" model and predates the loadable support.Tests
FindRefsTests.cshas decent happy-path coverage (LeadingEdge bundles, chain shapes, stop-at-first-asset, schema-version and empty-refs errors). Add:-nasserting per-section chain counts (pins the bug 2 fix);-iwith a nonexistent id (pins the bug 3 fix);Open questions
find-refsshould proactively note when the target is inassetbundle_assetseven when chains are found (it is useful context either way).